// 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;
}
}
}
}