// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the Apache 2.0 License. // See the LICENSE file in the project root for more information. using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace System.Linq { public static partial class EnumerableEx { /// /// Generates a sequence of accumulated values by scanning the source sequence and applying an accumulator function. /// /// Source sequence element type. /// Accumulation type. /// Source sequence. /// Accumulator seed value. /// /// Accumulation function to apply to the current accumulation value and each element of the /// sequence. /// /// Sequence with all intermediate accumulation values resulting from scanning the sequence. public static IEnumerable Scan(this IEnumerable source, TAccumulate seed, Func accumulator) { if (source == null) throw new ArgumentNullException(nameof(source)); if (accumulator == null) throw new ArgumentNullException(nameof(accumulator)); return source.Scan_(seed, accumulator); } /// /// Generates a sequence of accumulated values by scanning the source sequence and applying an accumulator function. /// /// Source sequence element type. /// Source sequence. /// /// Accumulation function to apply to the current accumulation value and each element of the /// sequence. /// /// Sequence with all intermediate accumulation values resulting from scanning the sequence. public static IEnumerable Scan(this IEnumerable source, Func accumulator) { if (source == null) throw new ArgumentNullException(nameof(source)); if (accumulator == null) throw new ArgumentNullException(nameof(accumulator)); return source.Scan_(accumulator); } private static IEnumerable Scan_(this IEnumerable source, TAccumulate seed, Func accumulator) { var acc = seed; foreach (var item in source) { acc = accumulator(acc, item); yield return acc; } } private static IEnumerable Scan_(this IEnumerable source, Func accumulator) { var hasSeed = false; var acc = default(TSource); foreach (var item in source) { if (!hasSeed) { hasSeed = true; acc = item; continue; } acc = accumulator(acc, item); yield return acc; } } } }