Skip to content

Latest commit

 

History

History
93 lines (80 loc) · 3.77 KB

aggregate.md

File metadata and controls

93 lines (80 loc) · 3.77 KB

Aggregate

Applies multiple accumulators sequentially in a single pass over a sequence.

In the example below, Aggregate is used to run the following seven accumulators:

  • sum of all numbers
  • sum of even numbers
  • count of numbers
  • smallest number
  • largest number
  • distinct number of digits across all numbers
  • list of numbers

concurrently, and in a single pass, over a sequence of integers:

Enumerable
    .Range(1, 10)
    .Shuffle()
    .Select(n => new { Num = n, Str = n.ToString(CultureInfo.InvariantCulture) })
    .Aggregate(
        0, (s, e) => s + e.Num,
        0, (s, e) => e.Num % 2 == 0 ? s + e.Num : s,
        0, (s, _) => s + 1,
        (int?)null, (s, e) => s is int n ? Math.Min(n, e.Num) : e.Num,
        (int?)null, (s, e) => s is int n ? Math.Max(n, e.Num) : e.Num,
        new HashSet<int>(), (s, e) => { s.Add(e.Str.Length); return s; },
        new List<(int, string)>(), (s, e) => { s.Add((e.Num, e.Str)); return s; },
        (sum, esum, count, min, max, lengths, items) => new
        {
            Sum           = sum,
            EvenSum       = esum,
            Count         = count,
            Average       = (double)sum / count,
            Min           = min is int mn ? mn : throw new InvalidOperationException(),
            Max           = max is int mx ? mx : throw new InvalidOperationException(),
            UniqueLengths = "[" + string.Join(", ", lengths) + "]",
            Items         = "[" + string.Join(", ", items)   + "]",
        })

Writing each aggregator this way can be tedious, repetitive and error-prone because you cannot, for example, reuse Enumerable.Sum but there is a set of experimental overloads (that live in the MoreLinq.Experimental namespace) that allow aggregators to be written as reactive comprehensions. This enables you to use aggregators from System.Reactive. The next example is logically the same as the previous, except it uses the overload where aggregators from System.Reactive are reused.

Enumerable
    .Range(1, 10)
    .Shuffle()
    .Select(n => new { Num = n, Str = n.ToString(CultureInfo.InvariantCulture) })
    .Aggregate(
        s => s.Sum(e => e.Num),
        s => s.Select(e => e.Num).Where(n => n % 2 == 0).Sum(),
        s => s.Count(),
        s => s.Min(e => e.Num),
        s => s.Max(e => e.Num),
        s => s.Select(e => e.Str.Length).Distinct().ToArray(),
        s => s.ToList(),
        (sum, esum, count, min, max, lengths, items) => new
        {
            Sum           = sum,
            EvenSum       = esum,
            Count         = count,
            Average       = (double)sum / count,
            Min           = min,
            Max           = max,
            UniqueLengths = "[" + string.Join(", ", lengths) + "]",
            Items         = "[" + string.Join(", ", items)   + "]",
        })

For more details, see the documentation.


✏ Edit this page if you see a typo or wish to contribute an improvement. Alternatively, you can also report an issue you see.