Aggregate method

T Aggregate ([Aggregator<T> aggregator, T initialValue ])

Aggregates the enumerable into a single value.

Aggregates the source enumerable by applying the aggregator function to each value in the collection in the order they appear. The result is a single value that is the result of the aggregation.

The initialValue parameter can be optionally applied, otherwise it defaults to a predefined value for primitive types and null for everything else.

The aggregator function offers two parameters - the accumulator and the value. In each iteration, the accumulator represents the running result of the aggregation and the value represents the current element to process. The function should return what the next value of the aggregation should be, and that value will become the accumulator on the next iteration. Once the aggregation is complete, the last value to be returned is considered the result of the aggregation process.

When the type of the enumerable is one of the below types, the aggregator function can be omitted. In this case, the function defaults to predefined aggregator functions depending on the type:

  • Numeric types (num, int, double) return the sum of all elements. The initial value is set to the zero equivalent of the type.
  • String types return all the elements concatenated into a single string. The initial value is an empty string.

If the enumerable type is not one of these types, the aggregator function must be provided. Otherwise, an ArgumentError will be thrown.

The Aggregate function will iterate over every element in the enumerable.

Implementation

T Aggregate([Aggregator<T> aggregator, T initialValue]) {
  if (aggregator == null &&
      T != num &&
      T != int &&
      T != double &&
      T != String)
    throw ArgumentError(
        '`aggregator` must not be null or the type of this enumerable must be one of the following: ${[
      num,
      int,
      double,
      String
    ]}');

  if (aggregator == null) {
    if (T == num)
      return EnumerableReducers.SumNum(this as Enumerable<num>) as T;
    if (T == int)
      return EnumerableReducers.SumInt(this as Enumerable<int>) as T;
    if (T == double)
      return EnumerableReducers.SumDouble(this as Enumerable<double>) as T;
    if (T == String)
      return EnumerableReducers.SumString(this as Enumerable<String>) as T;
    throw UnexpectedStateError();
  }

  dynamic result = initialValue;
  if (result == null) {
    if (T == int)
      result = 0;
    else if (T == double || T == num)
      result = 0.0;
    else if (T == bool)
      result = false;
    else if (T == String) result = '';
  }

  final iterator = this.iterator;
  if (!iterator.moveNext()) return result;

  result = aggregator(result, iterator.current);
  while (iterator.moveNext()) result = aggregator(result, iterator.current);

  return result;
}