Skip to main content
This revision made January 06, 2012 21:41, by Kin-man Chung

EL Collection Operations

Introduction

EL 3.0 uses LINQ (.NET Language-Integrated Query) as a basis for the query expressions on collections. It provides a default implementation of the operators in The .NET Standard Query Operators.

There are several advantages in adopting LINQ. LINQ is an industrial standard and has many providers (e.g. LINQ to XML and LINQ to SQL). Although the syntax EL 3.0 used is slightly different from what's used in say C#, users familiar with LINQ should feel at home with EL 3.0. The LINQ operators are powerful, complete, and extendable, and their inclusion provides a full support for collections in EL 3.0.

The support for the query operators in EL 3.0 is left in the implementation. The method, ExpressionFactory.getQueryOperatorELResolver() is added to the API to retrieve an instance of an ELResolver that implements the methods for the operators. A conforming implementation must implement the methods described below.

Additionally, a couple of new EL constructs have been added to EL 3.0, to complete the support of the query operators:

  1. Lambda Expression. See LambdaExpression for details.
  2. Collection construction. See CollectionConstruction for details.

Methods as operators

Operations on collections are performed by calling the built-in methods. The build-in methods are not actual methods of the collection objects, and are implemented in the appropriate ELResolver. To an user, they look and behave like real methods.

Some examples will make this clear.

The following computes the average of a list, using the built-in method "average":

    [1,2,3].average()

The following creates a list of maps containing the name and price of the products with the price greater than 10, using the built-in method "where" and "select". Both methods returns a collection, hence the use of cascading "." operators here.

    products.
        where(p -> p.price > 10).
        select(p -> {"name": p.name, "price": p.price}})

Note the use of map constructor and lambda expressions here.

From now on, in the context of collection operations, the terms operator and method will be used interchangeably.

In EL 3.0, the method ExpressionFactory.getQueryOperatorELResolver() has been added to return the ELResolver that implements the operators. This ELResolver should be placed before the BeanELResolver (but after the user defined ELResolvers) in the ELResolver chain, and must intercept all calls to the methods that implement the operators, listed below.

The base object for these methods must be an instance of java.lang.Iterable. In most of the case, the methods return a java.lang.Iterable, which can be used to call another method. The use of a java.lang.Iterable instead of a java.util.Collection avoids the construction of a Collection instance in most cases.

If the base object is a Map, then its Set view of the mappings (i.e. Map.entrySet()) is used in the methods. If the base object is an array, it is converted to a List.

For calls to methods not in the list, or if the base object is not an Iterable, a Map, or an array, this ELResolver must return without resolution, allowing other ELResolvers down the chain to try to resolve the method calls. Note that query methods will override any methods that actually exist in the Collection object, and it is up to the implementation of these query methods to call the methods that actually exist as Java methods. An example of such a query method is "size", which can be implemented by calling java.util.Collection.size(), if the base object is a java.util.Collection.

Use of Lambda Expressions in Operators

In some methods, one or more Lambda expressions are passed to the method. They are usually used to specify a condition, or to select a field of a class, or to transform from one object to another object, and are meant to be evaluated during the enumeration of the Collection object. The arguments to the Lambda expressions are usually members of some Collection. The precise definitions of these Lambda expressions used in the methods will be specified with the descriptions of the methods.

Since the Lambda expressions behave like functions, in the context of collection operators, they'll sometimes be referred as functions.

We use the notation (S, K) -> R to denote a function (Lambda Expression) that has two arguments of type S and K, and that evaluates to an object of type R. This notation, when used with the method notation, described below, helps to clarify the Collection members used in the evaluation of the functions, and the Collection members that are returned by the methods

Mapping C# types to Java Types

. In most cases, a C# class or interface can be mapped to a Java class or interface already exists in the Java language. In the cases where the query operatos refer to C# classes or interfaces that cannot be mapped to an existing Java class or interfaces, they are define in EL 3.0.

C# Type JDK Type EL Type
IEnumerable Iterable
Dictionary Map
Lookup<K,V> Map<K,Grouping<K,V>>
Comparer Comparator
IGrouping Grouping
InvalidOperationException InvalidOperationException

Operator Notation

Since the query methods are not Java methods, there will be no Javadocs for them. Instead, we use the following notation, for example,

    R Iterable<S>.oper(T1 arg1, T2 arg2)

to describe the method "oper" of Iterable<S>. The method returns an object R, and has two argument arg1 of type T1, and arg2 of type T2. As another example, we use

    Iterable<R> Iterable<S>.oper((S -> R) selector)

to describe the method "oper" of Iterable<S>. The method returns another Iterable<R>, and has one argument which is a function named "selector". Note the use of Iterable<S> and Iterable<R> here does not have the same meaning as the generic type in the Java language, They are used to indicate the function "selector" takes an element from the base object (of type Iterable<S>), and yields an element to the return object (of type Iterable<R>).

Restriction Operators

where

  Iterable<S> Iterable<S>.where((S->boolean) predicate)
  Iterable<S> Iterable<S>.where((S,int->boolean) predicate)

The Iterable returned by "where" enumerates the source sequence and yields those elements for which the predicate function returns true. The first argument of the predicate function represents the element to test. The second argument, if present, represents the zero-based index of the element within the source sequence.

Projection Operators

select

  Iterable<R> Iterable<S>.select((S -> R) selector)
  Iterable<R> Iterable<S>.select(((S, int) -> R) selector)

The Iterable returned by "select" enumerates the source sequence and yields the results of evaluating the selector Lambda for each element. The first argument of the selector represents the element to process. The second argument, if present, represents the zero-based index of the element within the source sequence.

selectMany

  Iterable<R> Iterable<S>.selectMany((S->Iterable<R>) selector)
  Iterable<R> Iterable<S>.selectMany(((S, int)->Iterable<R>) selector)
  Iterable<R> Iterable<S>.selectMany((S->Iterable<I>) selector, ((S,I)->R) resultSelector)
  Iterable<R> Iterable<S>.selectMany(((S, int)->Iterable<I>) selector, ((S, I)->R) resultSelector)

The Iterable returned by "selectMany" enumerates the source sequence. For each element (called the outer element), the selector Lambda is evaluated, and should results in an Iterable (called inner Iterable). The behavior would be undefined if the result of evaluating the selector Lambda is not an Iterable. The inner Iterable is then enumerated, and its element (called the inner element), is yielded, if there is no resultSelector Lambda. If there is a resultSelector Lambda, the outer and the inner element is passed to resultSelector, and the result of evaluating resultSelector is yielded. The second argument to the selector Lambda, if present, represents the zero-based index of the element within the source sequence.

Roughly speaking, selectMany can be used to flatten a List<List<R>> into a List<R>.

Partitioning Operators

take

  Iterable<R> Iterable<S>.take(int count)

The take operator yields a given number of elements from a sequence and then skips the remainder of the sequence.

The Iterable returned by "take" enumerates the source sequence and yields elements until the number of elements given by the count argument have been yielded or the end of the source is reached. If the count argument is less than or equal to zero, the source sequence is not enumerated and no elements are yielded.

skip

  Iterable<R> Iterable<S>.skip(int count)

The skip operator skips a given number of elements from a sequence and then yields the remainder of the sequence.

The Iterable returned by "skip" enumerates the source sequence, skipping the number of elements given by the count argument and yielding the rest. If the source sequence contains fewer elements than the number given by the count argument, nothing is yielded. If the count argument is less than or equal to zero, all elements of the source sequence are yielded.

takeWhile

  Iterable<R> Iterable<S>.takeWhile((S->boolean) predicate)
  Iterable<R> Iterable<S>.takeWhile(int, (S->boolean) predicate)

The takeWhile operator yields elements from a sequence while a test is true and then skips the remainder of the sequence.

The Iterable returned by "takeWhile" enumerates the source sequence, testing each element using the predicate function and yielding the element if the result was true. The enumeration stops when the predicate function returns false or the end of the source sequence is reached. The first argument of the predicate function represents the element to test. The second argument, if present, represents the zero-based index of the element within the source sequence.

skipWhile

  Iterable<R> Iterable<S>.skipWhile((S->boolean) predicate)
  Iterable<R> Iterable<S>.skipWhile(int, (S->boolean) predicate)

The skipWhile operator skips elements from a sequence while a test is true and then yields the remainder of the sequence.

The Iterable returned by "skipWhile" enumerates the source sequence, testing each element using the predicate function and skipping the element if the result was true. Once the predicate function returns false for an element, that element and the remaining elements are yielded with no further invocations of the predicate function. If the predicate function returns true for all elements in the sequence, no elements are yielded. The first argument of the predicate function represents the element to test. The second argument, if present, represents the zero-based index of the element within the source sequence.

Join Operators

join

  Iterable<R> Iterable<S>.join(Iterable<I> innerSequence, (S->K)outerSelector, (I->K) innerSelector, ((S,I)->R) resultSelector)
  Iterable<R> Iterable<S>.join(Iterable<I> innerSequence, (S->K)outerSelector, (I->K) innerSelector, ((S,I)->R} resultSelector, Comparator cmp)

The join operator performs an inner join of two sequences based on matching keys extracted from the elements.

The Iterable returned by "join" enumerates the source sequence, and for each element (called outer element), the outerSelector Lambda is evaluated, to a value (called key1). For each non-zero key1, innerSequence is enumerated, and for each element (called inner element), the innerSelector is evaluated, to a value (called key2). The value key1 is compared with key2, and if equal, resultSelector is evaluated (with outer element and inner element as the arguments), and the resulting object is yielded.

If the Comparator cmp is specified, it is used for the comparison of key1 to key2.

groupJoin

  Iterable<R> Iterable<S>.groupJoin(Iterable<I>innerSequence, (S->K)outerSelector, (I->K)innerSelector, ((S,Iterable<I>)->R)resultSelector)
  Iterable<R> Iterable<S>.groupJoin(Iterable<I>innerSequence, (S->K)outerSelector, (I->K)innerSelector, ((S,Iterable<I>)->R}resultSelector, Comparator cmp)

The groupJoin operator performs a grouped join of two sequences based on matching keys extracted from the elements.

The Iterable returned by "join" enumerates the source sequence, and for each element (called outer element), the outerSelector Lambda is evaluated, to a value (called key1). If key1 is non-zero, innerSequence is enumerated, and for each element (called inner element), innerSelector is evaluated, to a value (called key2). The resultSelector is evaluated, (with the outer element as its first arguement, and the sequence of inner elements whose key2 equals key1, as its second argument), and the resulting object is yielded.

If the Comparator cmp is specified, it is used for the comparison of key1 to key2.

Concatenation Operator

concat

  Iterable<R> Iterable<S>.concat(Iterable<S> second)

The Concat operator concatenates two sequences.

The Iterable returned from "concat" enumerates the source sequence, yielding each element, and then it enumerates the second sequence, yielding each element.

Ordering Operators

orderBy and thenBy

Operators in the orderBy/thenBy family of operators order a sequence according to one or more keys.

  Iterable<S> Iterable<S>.orderBy((S->K) keySelector)
  Iterable<S> Iterable<S>.orderBy((S->K) keySelector, Comparator cmp)
  Iterable<S> Iterable<S>.orderByDescending((S->K) keySelector)
  Iterable<S> Iterable<S>.orderByDescending((S->K) keySelector, Comparator cmp)
  Iterable<S> Iterable<S>.thenBy((S->K) keySelector)
  Iterable<S> Iterable<S>.thenBy((S->K) keySelector, Comparator cmp)
  Iterable<S> Iterable<S>.thenByDescending((S->K) keySelector)
  Iterable<S> Iterable<S>.thenByDescending((S->K) keySelector, Comparator cmp)

The orderBy, orderByDescending, thenBy, and thenByDescending operators make up a family of operators that can be composed to order a sequence by multiple keys. A composition of the operators has the form

  source.orderBy(...).thenBy(...).thenBy(...) ...

where orderBy(...) is an invocation of orderBy or orderByDescending and each thenBy(...), if any, is an invocation of thenBy or thenByDescending. The initial orderBy or orderByDescending establishes the primary ordering, the first thenBy or thenByDescending establishes the secondary ordering, the second thenBy or thenByDescending establishes the tertiary ordering, and so on. Each ordering is defined by:

  • A keySelector function that extracts the key value from an element.
  • An optional comparator for comparing key values. If no comparator is specified or if the comparator argument is null, the key value must implements Comparable, otherwise no sorting will be done with this key values.
  • A sort direction. The orderBy and thenBy methods establish an ascending ordering, the orderByDescending and thenByDescending methods establish a descending ordering.

Calling orderBy or orderByDescending on the result of an orderBy/thenBy operator will introduce a new primary ordering, disregarding the previously established ordering.

These operators perform a stable sort; that is, if the key values of two elements are equal, the order of the elements is preserved.

The order of the original collection object is not affected by these operators.

reverse

  Iterable<S> Iterable<S>.reverse()

The reverse operator reverses the elements of a sequence.

The Iterable returned from "reverse" enumerates the source sequence, collecting all elements, and then yields the elements of the source sequence in reverse order.

Grouping Operators

groupBy

  Iterable<Grouping<K,S>> Iterable<S>.groupBy((S->K) keySelector)
  Iterable<Grouping<K,S>> Iterable<S>.groupBy((S->K) keySelector, Comparator cmp)
  Iterable<Grouping<K,E>> Iterable<S>.groupBy((S->K) keySelector, (S->E) elementSelector)
  Iterable<Grouping<K,E>> Iterable<S>.groupBy((S->K) keySelector, (S->E) elementSelector, Comparator cmp)

The Iterable returned from "groupBy" enumerates the source sequence, and evaluates the keySelector and elementSelector (if present) functions once for each source element. The keySelector argument specifies a function that extracts the key value from a source element. The elementSelector argument, if present, specifies a function that maps a source element to a destination element. If no elementSelector is specified, the source elements become the destination elements. Once all key and destination element pairs have been collected, the destination elements with the same key value is grouped in a Grouping object, which is then yielded.

The groupings are yielded in the order in which their key values first occurred in the source sequence, and destination elements within a grouping are yielded in the order in which their source elements occurred in the source sequence.

Key values are compared using the Comparator cmp, if specified.

Set Operators

distinct

  Iterable<S> Iterable<S>.distinc()
  Iterable<S> Iterable<S>.distict(Comparator cmp)

The distinct operator eliminates duplicate elements from a sequence.

The Iterable returned from "distinct" enumerates the source sequence, yielding each element that has not previously been yielded. If a non-null comparer argument is supplied, it is used to compare the elements.

union

  Iterable<S> Iterable<S>.union(Iterable<S> second)
  Iterable<S> Iterable<S>.union(Iterable<S> second, Comparator cmp)

The union operator produces the set union of two sequences.

The Iterable returned from "union" enumerates the source and second sequences, in that order, yielding each element that has not previously been yielded. If a non-null comparator argument is supplied, it is used to compare the elements.

intersect

  Iterable<S> Iterable<S>.intersect(Iterable<S> second)
  Iterable<S> Iterable<S>.intersect(Iterable<S> second, Comparator cmp)

The Intersect operator produces the set intersection of two sequences.

The Iterable returned from "intersect" enumerates the source sequence, yielding each element that has not previously been yielded, and which is also contained in the second sequence. If a non-null comparator argument is supplied, it is used to compare the elements.

except

  Iterable<S> Iterable<S>.exceptt(Iterable<S> second)
  Iterable<S> Iterable<S>.except(Iterable<S> second, Comparator cmp)

The except operator produces the set difference between two sequences.

The Iterable returned from "except" enumerates the source sequence, yielding each element that has not previously been yielded, and which is not contained in the second sequence. If a non-null comparator argument is supplied, it is used to compare the elements.

Conversion Operators

toArray

  S[] Iterable<S>.toArray()

The toArray operator enumerates the source sequence and returns an array containing the elements of the sequence.

toList

  List<S> Iterable<S>.toList()

The toList operator enumerates the source sequence and returns a List<S> containing the elements of the sequence.

toMap

  Map<K, S> Iterable<S>.toMap((S->K) keySelector)
  Map<K, S> Iterable<s>.toMap((S->K) keySelector, Comparator cmp)
  Map<K, V> Iterable<S>.toMap((S->K) keySelector, (S->V) elementSelector)
  Map<K, V> Iterable<s>.toMap((S->K) keySelector, (S->V) elementSelector, Comparator cmp)

The toMap operator enumerates the source sequence and evaluates the keySelector and elementSelector functions for each element to produce that element's key and value. The resulting key and value pairs are returned in a Map. If no elementSelector was specified, the value for each element is simply the element itself. If a non-null comparator argument is supplied, it is used to compare the keys.

toLookup

  Map<K,Grouping<K,S>> Iterable<S>.toLookup((S->K) keySelector)
  Map<K,Grouping<K,S>> Iterable<S>.toLookup((S->K) keySelector, Comparator cmp)
  Map<K,Grouping<K,V>> Iterable<S>.toLookup((S->K) keySelector, (S->V) elementSelector)
  Map<K,Grouping<K,V>> Iterable<S>.toLookup((S->K) keySelector, (S->V) elementSelector, Comparator cmp)

The toLookup operator enumerates the source sequence and evaluates the keySelector and elementSelector functions for each element to produce that element's key and value. The values with the same key are grouped in a Grouping, and the key and the Grouping are returned in a Map. If no elementSelector was specified, the value for each element is simply the element itself. If a non-null comparator argument is supplied, it is used to compare the keys.

Equality Operator

sequenceEqual

  %roduce that element's key and value. The resulting key and value pairs are returned in a Map. If no elementSelector was specified, the value for each element is simply the element itself. If a non-null comparator argument is supplied, it is used to compare the keys.

toLookup

  Map<K,Grouping<K,S>> Iterable<S>.toLookup((S->K) keySelector)
  Map<K,Grouping<K,S>> Iterable<S>.toLookup((S->K) keySelector, Comparator cmp)
  Map<K,Grouping<K,V>> Iterable<S>.toLookup((S->K) keySelector, (S->V) elementSelector)
  Map<K,Grouping<K,V>> Iterable<S>.toLookup((S->K) keySelector, (S->V) elementSelector, Comparator cmp)

The toLookup operator enumerates the source sequence and evaluates the keySelector and elementSelector functions for each element to produce that element's key and value. The values with the same key are grouped in a Grouping, and the key and the Grouping are returned in a Map. If no elementSelector was specified, the value for each element is simply the element itself. If a non-null comparator argument is supplied, it is used to compare the keys.

Equality Operator

sequenceEqual

   Iterable<S>.sequenceEqual(Iterable<S> second)
   Iterable<S>.sequenceEqual(Iterable<S> second, Comparator cmp)

The SequenceEqual operator enumerates the two source sequences in parallel and compares corresponding elements. The method returns true if all corresponding elements compare equal and the two sequences are of equal length. Otherwise, the method returns false.

If a non-null comparer argument is supplied, it is used to compare the elements.

Element Operators

first

  <S> Iterable<S>.first()
  <S> Iterable<S>.first((S->boolean) 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.

An InvalidOperationException is thrown if no element matches the predicate or if the source sequence is empty.

firstOrDefault

  <S> Iterable<S>.firstOrDefault()
  <S> Iterable<S>.firstOrDefault((S->boolean) predicate)

The "firstOrDefault" operator enumerates the source sequence and returns the first element for which the predicate function returns true. If no predicate function is specified, the "firstOrDefault" operator simply returns the first element of the sequence.

If no element matches the predicate or if the source sequence is empty, a null is returned.

last

  <S> Iterable<S>.last()
  <S> Iterable<S>.last((S->boolean) predicate)

The "last" operator enumerates the source sequence and returns the last element for which the predicate function returns true. If no predicate function is specified, the "last" operator simply returns the last element of the sequence.

An InvalidOperationException is thrown if no element matches the predicate or if the source sequence is empty.

lastOrDefault

  <S> Iterable<S>.lastOrDefault()
  <S> Iterable<S>.lastOrDefault((S->boolean) predicate)

The "lastOrDefault" operator enumerates the source sequence and returns the last element for which the predicate function returns true. If no predicate function is specified, the "lastOrDefault" operator simply returns the last element of the sequence.

If no element matches the predicate or if the source sequence is empty, a null is returned.

single

  <S> Iterable<S>.single()
  <S> Iterable<S>.singleOrDefault((S->boolean) predicate)

The "single" operator enumerates the source sequence and returns the single element for which the predicate function returns true. If no predicate function is specified, the "single" operator simply returns the single element of the sequence.

An InvalidOperationException is thrown if the source sequence is empty, contains no matching element or more than one matching element.

singleOrDefault

  <S> Iterable<S>.singleOrDefault()
  <S> Iterable<S>.singleOrDefaultOrDefault((S->boolean) predicate)

The "singleOrDefault" operator enumerates the source sequence and returns the single element for which the predicate function returns true. If no predicate function is specified, the "singleOrDefault" operator simply returns the single element of the sequence.

An InvalidOperationException is thrown if the source sequence contains more than one matching element. If no element matches the predicate or if the source sequence is empty, null is returned.

elementAt

  <S> Iterable<S>.elementAt(int index)

The "elementAt" operator first checks whether the source sequence implements List. If it does, List.get() is used to obtain the element at the given index. Otherwise, the source sequence is enumerated until index elements have been skipped, and the element found at that position in the sequence is returned.

An IndexOutOfBoundException is thrown if the index is less than zero or greater than or equal to the number of elements in the sequence.

elementAtOrDefault

  <S> Iterable<S>.elementAtOrDefault(int index)

The "elementAtOrDefault" operator first checks whether the source sequence implements List. If it does, List.get() is used to obtain the element at the given index. Otherwise, the source sequence is enumerated until index elements have been skipped, and the element found at that position in the sequence is returned.

A null is returned if the index is less than zero or greater than or equal to the number of elements in the sequence.

defaultEmpty

  Iterable<S> Iterable<S>.defaultEmpty()
  Iterable<S> Iterable<S>.defaultEmpty(S defaultValue)

The Iterable return by "defaultEmpty" enumerates the source sequence and yields its elements. If the source sequence is empty, a single element with the given default value is yielded. If no default value argument is specified, a null is yielded.

Generation Operaotrs

These operators are not Collection operators, since their base type are not Iterables. They will be implemented as EL functions.

Note that we don't include the "empty" operator, as Collections.EMPTY_LIST, Collections.EMPTY_MAP, and Collections.EMPTY_SET provide the same functionality.

range

  Iterable<Integer> linq:range(int start, int count)

The Iterable returned by the linq:range is a consecutive integer sequence of "count" integers, starting at "start".

repeat

  Iterable<S> linq:repeat(S element, int count)

The Iterable returned by linq:repeat is a sequence of "count" occurrences of "element".

Qualifier Operators

any

  boolean Iterable<S>.any()
  boolean Iterable<S>.any((S->boolean) predicate)

The "any" operator enumerates the source sequence 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 sequence contains any elements.

The enumeration of the source sequence is terminated as soon as the result is known.

all

  boolean Iterable<S>.all((S->boolean) predicate)

The "all" operator enumerates the source sequence and returns true if no element fails the test given by the predicate. It returns true if the sequence is empty.

The enumeration of the source sequence is terminated as soon as the result is known.

contains

  boolean Iterable<S>.contains(S element)

If the source Iterable is a Collection, Collection.contains() is invoked to obtain the result. Otherwise, the source sequence is enumerated to determine if it contains an element with the given value. If a matching element is found, the enumeration of the source sequence is terminated at that point.

Aggregate Operators

count

  Number Iterable<S>.count()
  Number Iterable<S>.count((S->boolean) predicate)

The "count" operator without a predicate first checks whether the source sequence implements Collection. If it does, Collection.size() is used to obtain the element count. Otherwise, the source sequence is enumerated to count the number of elements.

The count operator with a predicate enumerates the source sequence and counts the number of elements for which the predicate function returns true.

sum

  Number Iterable<Number>.sum()
  Number Iterable<S>.sum((S->Number) selector)

The "sum" operator enumerates the source sequence, 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 sequence. Furthermore, the operator does not include null values in the result.

min

  S Iterable<S>.min()
  R Iterable<S>.min((S->R) selector)

The min operator enumerates the source sequence, 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 (which must be Number's) is computed. The values to be compared must implement Comparable.

max

  S Iterable<Sr>.max()
  R Iterable<S>.max((S->R) selector)

The max operator enumerates the source sequence, 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 (which must be Number's) is computed. The values to be compared must implement Comparable.

average

  Number Iterable<Number>.average()
  Number Iterable<S>.average((S->Number) selector)

The average operator enumerates the source sequence, invokes the selector funct

Difference compared to previous revision
<span>|IGrouping | |Grouping |<span style="text-decoration:underline;color:green">- |InvalidOperationException | |InvalidOperationException |</span>} ==Operator Notation== ... ==Equality Operator== ===sequenceEqual=== <span style="text-decoration:underline;color:green">%roduce that element's key and value. The resulting key and value pairs are returned in a Map. If no elementSelector was specified, the value for each element is simply the element itself. If a non-null comparator argument is supplied, it is used to compare the keys. ===toLookup=== </span><nowiki><span style="text-decoration:underline;color:green">Map<K,Grouping<K,S>></span> Iterable<S>.<span style="text-decoration:underline;color:green">toLookup((S->K) keySelector)</nowiki> <nowiki>Map<K,Grouping<K,S>> Iterable<S>.toLookup((S->K) keySelector, Comparator cmp)</nowiki> <nowiki>Map<K,Grouping<K,V>> Iterable<S>.toLookup((S->K) keySelector, (S->V) elementSelector)</nowiki> <nowiki>Map<K,Grouping<K,V>> Iterable<S>.toLookup((S->K) keySelector, (S->V) elementSelector, Comparator cmp)</nowiki> The toLookup operator enumerate</span>s<span style="text-decoration:underline;color:green"> th</span>e<span style="text-decoration:underline;color:green"> source se</span>quence<span style="text-decoration:underline;color:green"> and evaluates the keySelector and elementSelector functions for each element to produce that element's key and value. The values with the same key are grouped in a Grouping, and the key and the Grouping are returned in a Map. If no elementSelector was specified, the value for each element is simply the element itself. If a non-null comparator argument is supplied, it is used to compare the keys. ==</span>Equal<span style="text-decoration:underline;color:green">ity Operator== ===sequenceEqual=== <nowiki> Iterable<S>.sequenceEqual</span>=EL Collection Operations= ==Introduction== EL 3.0 uses [http://msdn.microsoft.com/en-us/library/bb308959.aspx LINQ] (.NET Language-Integrated Query) as a basis for the query expressions on collections. It provides a default implementation of the operators in [http://msdn.microsoft.com/en-us/library/bb394939.aspx The .NET Standard Query Operators]. ... <nowiki>Number Iterable<Number>.average()</nowiki> <nowiki>Number Iterable<S>.average((S->Number) selector)</nowiki> The average operator enumerates the source sequence, invokes the selector funct<span style="text-decoration:line-through;color:red">ion for each element, and finds the average of the resulting values. If no selector function is specified, the average of the elements themselves (which must be Number's) is computed. ===aggregate=== <nowiki>S Iterable<S>.aggregate(((S,S)->S) func)</nowiki> <nowiki>S Iterable<S>.aggregate(A seed, ((A,S)->A) func)</nowiki> <nowiki>R Iterable<S>.aggregate(A seed, ((A,S)->A) func, (A->R) resultSelector)</nowiki> The aggregate operators with a seed value start by assigning the seed value to an internal accumulator. They then enumerate the source sequence, repeatedly computing the next accumulator value by invoking the specified function with the current accumulator value as the first argument and the current sequence 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. The Aggregate operator without a seed value uses the first element of the source sequence as the seed value, but otherwise functions as described above. If the source sequence is empty, the Aggregate operator without a seed value throws an InvalidOperationException. </span><span>
 
 
Close
loading
Please Confirm
Close