Scan.cs 3.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the Apache 2.0 License.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Collections.Generic;
  5. namespace System.Linq
  6. {
  7. public static partial class EnumerableEx
  8. {
  9. /// <summary>
  10. /// Generates a sequence of accumulated values by scanning the source sequence and applying an accumulator function.
  11. /// </summary>
  12. /// <typeparam name="TSource">Source sequence element type.</typeparam>
  13. /// <typeparam name="TAccumulate">Accumulation type.</typeparam>
  14. /// <param name="source">Source sequence.</param>
  15. /// <param name="seed">Accumulator seed value.</param>
  16. /// <param name="accumulator">
  17. /// Accumulation function to apply to the current accumulation value and each element of the
  18. /// sequence.
  19. /// </param>
  20. /// <returns>Sequence with all intermediate accumulation values resulting from scanning the sequence.</returns>
  21. public static IEnumerable<TAccumulate> Scan<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
  22. {
  23. if (source == null)
  24. throw new ArgumentNullException(nameof(source));
  25. if (accumulator == null)
  26. throw new ArgumentNullException(nameof(accumulator));
  27. return source.Scan_(seed, accumulator);
  28. }
  29. /// <summary>
  30. /// Generates a sequence of accumulated values by scanning the source sequence and applying an accumulator function.
  31. /// </summary>
  32. /// <typeparam name="TSource">Source sequence element type.</typeparam>
  33. /// <param name="source">Source sequence.</param>
  34. /// <param name="accumulator">
  35. /// Accumulation function to apply to the current accumulation value and each element of the
  36. /// sequence.
  37. /// </param>
  38. /// <returns>Sequence with all intermediate accumulation values resulting from scanning the sequence.</returns>
  39. public static IEnumerable<TSource> Scan<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
  40. {
  41. if (source == null)
  42. throw new ArgumentNullException(nameof(source));
  43. if (accumulator == null)
  44. throw new ArgumentNullException(nameof(accumulator));
  45. return source.Scan_(accumulator);
  46. }
  47. private static IEnumerable<TAccumulate> Scan_<TSource, TAccumulate>(this IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
  48. {
  49. var acc = seed;
  50. foreach (var item in source)
  51. {
  52. acc = accumulator(acc, item);
  53. yield return acc;
  54. }
  55. }
  56. private static IEnumerable<TSource> Scan_<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
  57. {
  58. var hasSeed = false;
  59. var acc = default(TSource);
  60. foreach (var item in source)
  61. {
  62. if (!hasSeed)
  63. {
  64. hasSeed = true;
  65. acc = item;
  66. continue;
  67. }
  68. acc = accumulator(acc, item);
  69. yield return acc;
  70. }
  71. }
  72. }
  73. }