Cpplinq Query Operators

cpplinq is a C++ library that provides API that enable LINQ-like manipulation of collections in native code.

The examples in this document are all written in C++11 and assume the query operators have been imported using the using clause:
using namespace cpplinq;

Restriction Operators

where

The where operator filters a sequence based on a predicate.
template<typename TPredicate>
detail::where_builder<TPredicate> where (TPredicate predicate);
In the following example where is used to filter the even numbers from an array of integers.
int numbers[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
auto c = from_array(numbers)
         >> where([](int i) {return i%2==0})
         >> count();

Project Operators

ref

The ref operator projects a sequence of references into a sequence of std::reference_wrapper. This is used to avoid copies when the result is a STL container. STL containers doesn't support bare reference so in order to avoid copies the references needs to be wrapped.
detail::ref_builder ref ();
In the following example ref is used to wrap a sequence of customer references as a sequence of customer references wrapper before storing them in a vector.
// ref_result is a std::vector<std::reference_wrapper<customer const>>
auto ref_result =
        from_array (customers)
    >>  ref ()
    >>  to_vector ()
    ;

select

The select operator performs a projection over a sequence.
template<typename TPredicate>
detail::select_builder<TPredicate> select (TPredicate predicate);
In the following example select is used to retrieve the ID of customers from a sequence of customers.
auto ids = from_array (customers) 
           >>  select ([](customer const & c){return c.id;}) 
           >>  to_vector ();

select_many

The select_many operator performs a one-to-many element projection over a sequence.
template<typename TPredicate>
detail::select_many_builder<TPredicate> select_many (TPredicate predicate);
The following example creates a list of orders from all customers located in London.
auto order_rows =
        from_array (customers)
    >>  select_many ([](customer const & c) { return from (c.orders); })
    >>  select_many ([](order const & o) { return from (o.order_rows); })
    >>  to_vector ()
    ;

Partitioning Operators

take

The take operator creates a new sequence from a given sequence, keeping the first given number of elements and skipping the remainder of the sequence.
detail::take_builder take (size_type count);
The following example shows how to retrieve the last 5 created customers, given that the customer ID is a unique number, automatically incremented.
auto last_customers = from_array(customers)
                      >> orderby_descending([](customer const &c) {return c.ID;})
                      >> take(5)
                      >> to_vector();

take_while

The take operator creates a new sequence from a given sequence, keeping elements as long as a predicate applied to the element holds true and skipping the remainder of the sequence.
template<typename TPredicate>
detail::take_while_builder<TPredicate> take_while (TPredicate predicate);
The following example creates a new sequence with the first elements of the original sequence that are smaller than 5.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};
auto result = from_array(numbers)
              >> take_while([](int i) {return i < 5;})
              >> to_vector();

skip

The skip operator creates a new sequence from a given sequence, skipping a given number of elements and taking the rest of the sequence.
detail::skip_builder skip (size_type count);
The following example creates a sequence of all but the first 5 numbers from an array.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};
auto result = from_array(numbers)
              >> skip(5)
              >> to_vector();

skip_while

The skip_while operator creates a new sequence from a given sequence, skipping elements as long as a predicate applied to each element holds true and taking the rest of the sequence.
template <typename TPredicate>
detail::skip_while_builder<TPredicate> skip_while (TPredicate predicate);
The example below creates a new sequence of numbers from the original sequence starting with the first element that is greater than 6.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};
auto result = from_array(numbers)
              >> skip_while([](int i) {return i<5;})
              >> to_vector();

Join Operators

join

The join operator performs an inner join of two sequences based on matching keys extracted from the elements.
template<typename TOtherRange, typename TKeySelector, typename TOtherKeySelector, typename TCombiner>
detail::join_builder<TOtherRange, TKeySelector, TOtherKeySelector, TCombiner> join (
                TOtherRange         other_range,   
                TKeySelector        key_selector,   
                TOtherKeySelector   other_key_selector,   
                TCombiner           combiner);
The other_key_selector and key_selector arguments specify functions that extract the join key values from elements of the outer (other_range) and inner (source range) sequences, respectively. The combiner argument specifies a function that creates a result element from two matching outer and inner sequence elements.

When the object returned by join is enumerated, it first enumerates the inner sequence and evaluates the key_selector function once for each inner element, collecting the elements by their keys in a multimap. Once all inner elements and keys have been collected, the outer sequence is enumerated. For each outer element, the other_key_selector function is evaluated and, if non-null, the resulting key is used to look up the corresponding inner elements in the multimap. For each matching inner element (if any), the combiner function is evaluated for the outer and inner element pair, and the resulting object is yielded.

The join operator preserves the order of the outer sequence elements, and for each outer element, the order of the matching inner sequence elements.

The following examples shows how to join a sequence of customers and customers_addresses.
struct customer
{
    std::size_t     id          ;
    std::string     first_name  ;
    std::string     last_name   ;
};

struct customer_address
{
    std::size_t     id          ;
    std::size_t     customer_id ;
    std::string     country     ;
};

customer customers[] = 
{
    customer (1 , "Bill"    , "Gates"   ),
    customer (2 , "Steve"   , "Jobs"    ),
    customer (3 , "Richard" , "Stallman"),
    customer (4 , "Linus"   , "Torvalds"),
};

customer_address customer_addresses[] =
{
    customer_address (1, 1, "USA"       ),
    customer_address (2, 4, "Finland"   ),
    customer_address (3, 4, "USA"       ),
};

auto result = 
       from_array(customers)                                                                   
    >> join (
            from_array(customer_addresses),
            [](customer const & c) {return c.id;},
            [](customer_address const & ca) {return ca.customer_id;},
            [](customer const & c, customer_address const & ca) {return std::make_pair (c, ca);},
       )
    >> to_vector();

Concatenation Operators

concat

The concat operator concatenates two sequences.
template <typename TOtherRange>
detail::concat_builder<TOtherRange> concat(TOtherRange other_range);
When the object returned by concat is enumerated, it enumerates the first sequence, yielding each element, and then it enumerates the second sequence, yielding each element. When both sequences are empty the result is an empty sequence.
auto result = range(0,5) >> concat (range(5,5)) >> to_vector(); // yields {0,1,2,3,4,5,6,7,8,9}

Ordering Operators

orderby, thenby, orderby_ascending, orderby_descending, thenby_ascending, thenby_descending

These operators are used to order a sequence by one or more keys. They can combined to order a sequence by multiple keys in the form (as an example):
from(source) >> orderby_xxx(..) >> thenby_xxx()
where orderby_xxx can be either orderby, orderby_ascending or orderby_descending and thenby_xxx can be either thenby, thenby_ascending or thenby_descending.
template<typename TPredicate>
detail::orderby_builder<TPredicate> orderby (TPredicate predicate, bool sort_ascending  = true);

template<typename TPredicate>
detail::orderby_builder<TPredicate> orderby_ascending (TPredicate predicate);

template<typename TPredicate>
detail::orderby_builder<TPredicate> orderby_descending (TPredicate predicate);

template<typename TPredicate>
detail::thenby_builder<TPredicate> thenby (TPredicate predicate, bool sort_ascending  = true);

template<typename TPredicate>
detail::thenby_builder<TPredicate> thenby_ascending (TPredicate predicate);

template<typename TPredicate>
detail::thenby_builder<TPredicate> thenby_descending (TPredicate predicate);
The following examples order a sequence of customers by last name (ascending), then by first name (ascending) and finally by birthdate (descending).
auto sequence = from_array (customers) 
                   >>  orderby ([] (customer const & c) {return c.last_name;}, true)
                   >>  thenby ([] (customer const & c) {return c.first_name;}, false)
                   >>  thenby_descending ([] (customer const & c) {return c.birthdate;})
                   >>  to_vector ();
The orderby/thenby operators perform a stable sort; that is, if the key values of two elements are equal, the order of the elements is preserved. In contrast, an unstable sort does not preserve the order of elements that have equal key values.

reverse

The reverse operator reverses the elements of a range.
detail::reverse_builder reverse();
When the object returned by reverse is enumerated, it enumerates the source range, collecting all elements, and then yields the elements of the source revenge in reverse order. The original sequence is not enumerated until you start enumerating on the result sequence. Once the enumeration of the result start, the original sequence is enumerated entirely. Reversing an empty sequence yields an empty sequence.
auto result = range(0,10) >> reverse() >> to_vector(); // result is {9,8,7,6,5,4,3,2,1,0}

Set Operators

distinct

The distinct operator eliminates duplicate elements from a sequence.
detail::distinct_builder distinct();
When the object returned by distinct is enumerated it yields the elements from the original range that have not been already yielded, in the order they were encountered. If the original range is empty, the result is also an empty range.
int numbers[] = {5,4,3,2,1,2,3,4,5};
auto result = from_array(numbers) >> distinct() >> to_vector(); // yields {5,4,3,2,1}

union_with

The union_with operator produces the set union of two sequences.
template <typename TOtherRange>
detail::union_builder<TOtherRange> union_with(TOtherRange other_range);
When the object returned by union_with is enumerated, it enumerates the first and second sequences, in that order, yielding each element that has not previously been yielded. The original ranges are not enumerated until the returned object is enumerated.
auto result = empty<int>() >> union_with(range(1,5)) >> to_vector(); // yields {1,2,3,4,5}

int set1[] = {5,4,3,2,1,2,3,4,5};
int set2[] = {4,5,6,7};
auto set3 = from_array(set1) >> union_with(from_array(set2)) >> to_vector(); // yields {5,4,3,2,1,6,7}
auto set4 = from_array(set2) >> union_with(from_array(set1)) >> to_vector(); // yields {4,5,6,7,3,2,1}

intersect_with

The intersect_with operator produces the set intersection of two sequences.
template <typename TOtherRange>
detail::intersect_builder<TOtherRange> intersect_with(TOtherRange other_range);
When the object returned by intersect_with is enumerated, it enumerates the first sequence, collecting all distinct elements of that sequence. It then enumerates the second sequence, removing those elements that were also contained in the first sequence. It finally yields the remaining elements in the order in which they were collected. If one of the two intersected sequences is empty, the result is also an empty sequence.
auto set1 = empty<int>() >> intersect_with( range(0, 10) ) >> to_vector(); // yields {}
auto set2 = range(0, 10) >> intersect_with( empty<int>() ) >> to_vector(); // yields {}
int set1[] = {5,4,3,2,1,2,3,4,5};
int set2[] = {4,5,6};
auto set3 = from_array(set1) >> intersect_with(from_array(set2)) >> to_vector(); // yields {5,4}
auto set3 = from_array(set2) >> intersect_with(from_array(set1)) >> to_vector(); // yields {4,5}

except

The except operator produces the set difference between two sequences.
template <typename TOtherRange>
detail::except_builder<TOtherRange> except(TOtherRange other_range);
When the object returned by except is enumerated, it enumerates the first sequence, collecting all distinct elements of that sequence. It then enumerates the second sequence, removing those elements that were also contained in the first sequence. It finally yields the remaining elements in the order in which they were collected. If the first sequence is empty, the result is an empty sequence. If the second sequence is empty, the result is the distinct set of the first sequence.
auto set1 = empty<int>() >> except( range(0, 10) ) >> to_vector(); // yields {}
auto set2 = range(0, 10) >> except( empty<int>() ) >> to_vector(); // yields {0,1,2,3,4,5,6,7,8,9}
int set1[] = {5,4,3,2,1,2,3,4,5};
int set2[] = {4,5,6,7};
auto set3 = from_array(set1) >> except(from_array(set2)) >> to_vector(); // yields {3,2,1}
auto set4 = from_array(set2) >> except(from_array(set1)) >> to_vector(); // yields {6,7}

Conversion Operators

to_vector

Operator to_vector creates a std::vector<TValue> from a range, where TValue is the type of the elements of the range.
detail::to_vector_builder to_vector (size_type capacity = 16U);
If you know the number of elements in the sequence you can pass it to the operator, that allocates that number of elements before pushing them into the vector. This can improve the performance of the operator.
auto result = from_array(ints)
              >> to_vector();

to_list

Operator to_list creates a std::list<TValue> from a range, where TValue is the type of the elements of the range.
detail::to_list_builder to_list();
auto result = from_array(ints)
              >> to_list();

to_map

Operator to_map creates a std::map<TKey, TValue> from a range. It takes a predicate that selects the value to use as the key for each element of the range.
template<typename TKeyPredicate>
detail::to_map_builder<TKeyPredicate> to_map(TKeyPredicate key_predicate);
In case of duplicates the first is kept.

In the following examples a map is created from an array of customers. The key is represented by the ID of the customer. Notice that if there are more customers with the same ID the first one will be added to the map.
auto to_map_result = from_array (customers) 
                     >> to_map ([](customer const & c){return c.id;});

to_lookup

The to_lookup operator creates a cpplinq::lookup<TKey, TElement> from a sequence.
template<typename TKeyPredicate>
detail::to_lookup_builder<TKeyPredicate> to_lookup(TKeyPredicate key_predicate);
Unlike std::map<TKey, TElement>, which implements a one-to-one dictionary that maps keys to single values. cpplinq::lookup<TKey, TElement> implements a one-to-many dictionary that maps keys to sequences of values.
The to_lookup operator enumerates the source sequence and evaluates the key_predicate for each element to produce that element's key and value. The resulting key and value pairs are returned in a cpplinq::lookup<TKey, TElement>.
customer_address customer_addresses[] =
{
   customer_address (2, 4, "Finland"   ),
   customer_address (3, 4, "USA"       ),
   customer_address (1, 1, "USA"       ),
};

auto lookup = from_array (customer_addresses) 
           >> to_lookup ([] (customer_address const & ca){return ca.customer_id;}); 

auto countries = lookup[4] 
              >> select([](customer_address const & ca) {return ca.country;}) 
              >> to_vector();  // yields {"Finland", "USA"}

Equality Operators

sequence_equal

The sequence_equal operator checks whether two sequences are equal.
template <typename TOtherRange>
detail::sequence_equal_builder<TOtherRange> sequence_equal(TOtherRange other_range);

template <typename TOtherRange, typename TComparer>
detail::sequence_equal_predicate_builder<TOtherRange, TComparer> sequence_equal (TOtherRange other_range, TComparer comparer);
The sequence_equal operator enumerates the two source sequences in parallel and compares corresponding elements. If a comparer argument is supplied, it is used to compare the elements. Otherwise the default operator== is used. The method returns true if all corresponding elements compare equal and the two sequences are of equal length. Otherwise, the method returns false. If the compared sequences are both empty the method returns true.
auto result1 = range(0,10) >> sequence_equal(range(0, 10)); // yields true

int set1[] = {1,2,3,4,5};
int set2[] = {1,2,4,5};
auto result = from_array(set1) >> sequence_equal(from_array(set2)); // yields false

Element Operators

first

The first operator returns the first element of a sequence, or throws cpplinq::sequence_empty_exception if no element is found.
detail::first_builder first ()

template <typename TPredicate>
detail::first_predicate_builder<TPredicate> first (TPredicate predicate);
The first operator enumerates the source sequence and returns the first element for which the predicate function returns true. If no predicate function is specified, the first operator simply returns the first element of the sequence. If no match is found or the sequence is empty cpplinq::sequence_empty_exception is thrown.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};
auto f1 = from_array(numbers) >> first(); // yields 3
auto f2 = from_array(numbers) >> first([](int i) {return i%2==0;}); // yields 4
auto f3 = from_array(numbers) >> first([](int i) {return i>9;}); // throws cpplinq::sequence_empty_exception

first_or_default

The first_or_default operator returns the first element of a sequence, or a default value if no element is found.
detail::first_or_default_builder first_or_default();

template <typename TPredicate>
detail::first_or_default_predicate_builder<TPredicate> first_or_default (TPredicate predicate);
The first_or_default operator enumerates the source sequence and returns the first element for which the predicate function returns true. If no predicate function is specified, the first_or_default operator simply returns the first element of the sequence. If no match is found or the sequence is empty the default value is returned.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};
auto f1 = from_array(numbers) >> first_or_default(); // yields 3
auto f2 = from_array(numbers) >> first_or_default([](int i) {return i%2==0;}); // yields 4
auto f3 = from_array(numbers) >> first_or_default([](int i) {return i>9;}); // yields 0

last_or_default

The last_or_default operator returns the last element of a sequence, or a default value if no element is found.
detail::last_or_default_builder last_or_default();

template <typename TPredicate>
detail::last_or_default_predicate_builder<TPredicate>  last_or_default(TPredicate predicate);
The last_or_default operator enumerates the source sequence and returns the last element for which the predicate function returned true. If no predicate function is specified, the last_or_default operator simply returns the last element of the sequence.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};
auto l1 = from_array(numbers) >> last_or_default(); // yields 6
auto l2 = from_array(numbers) >> last_or_default([](int i) {return i%2==1;}); // yields 9
auto l3 = from_array(numbers) >> last_or_default([](int i) {return i>9;}); // yields 0

element_at_or_default

The element_at_or_default operator returns the element at a given index in a sequence, or a default value if the index is out of range.
detail::element_at_or_default_builder element_at_or_default(size_type index);
The source range is enumerated until index elements have been skipped, and the element found at that position in the range is returned. If the index is less than zero or greater than or equal to the number of elements in the range, the default value for the type of the range elements is returned.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};
auto e1 = from_array(numbers) >> element_at_or_default(0); // yields 3
auto e2 = from_array(numbers) >> element_at_or_default(3); // yields 1
auto e3 = from_array(numbers) >> element_at_or_default(42); // yields 0

Generation Operators

range

The range operator generates a range of integral numbers.
detail::int_range range(int start, int count);
If count is smaller than 0, then it creates an empty range. If start + count -1 is larger than INT_MAX then it creates INT_MAX-count elements.

The following example creates a vector of integers with values between 10 and 99.
auto start = 10;
auto count = 90;
auto r = range(start, count);
         >> to_vector();

repeat

The repeat operator generates a range by repeating a value a given number of times.
template <typename TValue>
detail::repeat_range<TValue> repeat (TValue element, int count);
If count is smaller than zero then the operator creates an empty range.

The following example creates a list with 10 elements having the value "cpplinq".
auto r = repeat("cpplinq", 10)
         >> to_list();

empty

The empty operator returns an empty range of a given type.
template <typename TValue>
detail::empty_range<TValue> empty();
The following example creates an empty list of customers.
auto customers = empty<customer>()
                 >> to_list();

singleton

The singleton operator returns a range containing one single element.
template<typename TValue>
detail::singleton_range<typename detail::cleanup_type<TValue>::type> singleton (TValue&& value)
Usage of the singleton operator is illustrated by the sample below
auto result = singleton (1);  // yields 1

generate

The generate operator uses a generating function/predicate to produce its range. The operator is similiar to fold in functional languages.

template<typename TPredicate>
detail::generate_range<TPredicate> generate (TPredicate predicate)

The generate operator expects the function/predicate to return an optional value. If a value is returned the range continues. The following sample generates a range using a lambda function.

auto x = -1;
auto result = generate ([&]() { return (++x < 3) ?   to_opt (x) : to_opt<int> ();}) // yields 0, 1, 2

Quantifiers

any

The any operator checks whether any element of a sequence satisfies a condition.
detail::any_builder any();

template <typename TPredicate>
detail::any_predicate_builder<TPredicate> any(TPredicate predicate);
The any operator enumerates the source range and returns true if any element satisfies the test given by the predicate. If no predicate function is specified, the any operator simply returns true if the source range contains any elements.

The enumeration of the source range is terminated as soon as the result is known.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};

auto a1 = from_array(numbers) >> any(); // yields true
auto a2 = from_array(numbers) >> any([](int i) {return i>9;}); // yields false

all

The all operator checks whether all elements of a range satisfy a condition.
template <typename TPredicate>
detail::all_predicate_builder<TPredicate> all(TPredicate predicate);
The all operator enumerates the source range and returns true if no element fails the test given by the predicate. The enumeration of the source range is terminated as soon as the result is known. If the range is empty the operator returns true.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};

auto a1 = from_array(numbers) >> all([](int i) {return i%2==1;}); // yields false
auto a2 = from_array(numbers) >> all([](int i) {return i<10;}); // yields true

contains

The contains operator checks whether a range contains a given element.
template <typename TValue>
detail::contains_builder<TValue> contains(TValue value);

template <typename TValue, typename TPredicate>
detail::contains_predicate_builder<TValue, TPredicate> contains(TValue value, TPredicate predicate);
The range is enumerated to determine if it contains an element with the given value. If a matching element is found, the enumeration of the range is terminated at that point. If a non-null comparison predicate argument is supplied, it is used to compare the elements to the given value. Otherwise the default operator== is used to compare the elements.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};
auto c = from_array(numbers) >> contains(1); // yields true

bool result = from (customers) 
              >> contains (customer(1, "Bill", "Gates"), 
                           [](customer const& c1, customer const& c2) {return c1.id == c2.id;});

Aggregate Operators

count

The count operator counts the number of elements in a range.
detail::count_builder count();

template <typename TPredicate>
detail::count_predicate_builder<TPredicate> count(TPredicate predicate);
The source range is enumerated to count the number of elements. If a predicate is supplied the operator enumerates the range and counts the number of elements for which the predicate function returns true.

The following example counts the number of even numbers in an array.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};

auto c = from_array(numbers) >> count([](int i) {return i%2==0;}); // yields 2

sum

The sum operator computes the sum of a sequence of numeric values.
detail::sum_builder sum();

template<typename TSelector>
detail::sum_selector_builder<TSelector> sum(TSelector selector);
The sum operator enumerates the source range, invokes the selector function for each element, and computes the sum of the resulting values. If no selector function is specified, the sum of the elements themselves is computed. The sum operator returns zero for an empty range.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};

auto s1 = from_array(numbers) >> sum(); // yields 31
auto s2 = from_array(numbers) >> sum([](int i) {return i*i;}); // yields 173

min

The min operator finds the minimum of a range of numeric values.
detail::min_builder min();

template<typename TSelector>
detail::min_selector_builder<TSelector> min(TSelector selector);
The min operator enumerates the range, invokes the selector function for each element, and finds the minimum of the resulting values. If no selector function is specified, the minimum of the elements themselves is computed. If the range is empty then std::numeric_limits<TValue>::max() is returned, where TValue is the type of the elements of the range.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};

auto m1 = from_array(numbers) >> min(); // yields 1
auto m2 = from_array(numbers) >> min([](int i) {return i+i;}); // yields 2

max

The max operator finds the maximum of a range of numeric values.
detail::max_builder max();

template<typename TSelector>
detail::max_selector_builder<TSelector> max(TSelector selector);
The max operator enumerates the range, invokes the selector function for each element, and finds the maximum of the resulting values. If no selector function is specified, the maximum of the elements themselves is computed. If the range is empty then std::numeric_limits<TValue>::min() is returned, where TValue is the type of the elements of the range.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};

auto m1 = from_array(numbers) >> max(); // yields 9
auto m2 = from_array(numbers) >> min([](int i) {return i*i;}); // yields 81

avg

The avg operator computes the average of a range of numeric values.
detail::avg_builder avg();

template<typename TSelector>
detail::avg_selector_builder<TSelector>avg(TSelector selector);
The avg operator enumerates the range, invokes the selector function for each element, and computes the average of the resulting values. If no selector function is specified, the average of the elements themselves is computed. If the source range is empty, the avg operator returns the default value for that type.
std::vector<int> numbers;
auto a = from(numbers) >> avg(); // yields 0
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};

auto a1 = from_array(numbers) >> avg(); // yields 3
auto a2 = from_array(numbers) >> avg([](int i) {return i*i;}); // yields 21

aggregate

The aggregate operator applies a function over a sequence.
template <typename TAccumulate, typename TAccumulator>
detail::aggregate_builder<TAccumulate, TAccumulator> aggregate(TAccumulate seed, TAccumulator accumulator);

template <typename TAccumulate, typename TAccumulator, typename TSelector>
detail::aggregate_result_selector_builder<TAccumulate, TAccumulator, TSelector> aggregate(
          TAccumulate seed, 
          TAccumulator accumulator, 
          TSelector result_selector);
The aggregate operators starts by assigning the seed value to an internal accumulator. Then it enumerates the range, repeatedly computing the next accumulator value by invoking the specified function with the current accumulator value as the first argument and the current range element as the second argument. The operator without a result selector returns the final accumulator value as the result. The operator with a result selector passes the final accumulator value to the supplied result selector and returns the resulting value. If the range is empty it returns the value of the seed.
int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};

auto s = from_array(numbers) >> aggregate(0, [](int s, int i) {return s+i;}); // yields 31
auto p = from_array(numbers) >> aggregate(1, [](int s, int i) {return s*i;}); // yields 6480

Other Operators

pairwise

The pairwise operator groups adjacent elements into pairs.
detail::pairwise_builder pairwise();

The pairwise operator reads data from the source in a lazy manner, returning pairs of sequential elements. If the source range is empty or contains only one element, the returned range will be empty.

int numbers[] = {3, 1, 4, 1, 5, 9, 2, 6};
auto pairs = from_array(numbers) >> pairwise(); // yields (3,1), (1,4), (4,1), (1,5), (5,9), (9,2), (2,6)

zip_with

The zip_with operator pairs elements from two enumerations, returning one element for each pair.
template <typename TOtherRange>
detail::zip_with_builder<TOtherRange>  zip_with (TOtherRange other_range)

The zip_with operator reads data from the sources in a lazy manner, returning pairs of successfully extracted elements. The operator stops when any of the input ranges contain no more elements.

int a[] = {3, 1, 4};
int b[] = {5, 9, 2, 7};
auto zipped = from_array(a) >> zip_with(from_array(b)); // yields (3,5), (1,9), (4,2)

Last edited May 30, 2014 at 9:49 AM by marten_range, version 25

Comments

No comments yet.