Scan.cs 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. {
  25. throw new ArgumentNullException(nameof(source));
  26. }
  27. if (accumulator == null)
  28. {
  29. throw new ArgumentNullException(nameof(accumulator));
  30. }
  31. return ScanCore(source, seed, accumulator);
  32. }
  33. /// <summary>
  34. /// Generates a sequence of accumulated values by scanning the source sequence and applying an accumulator function.
  35. /// </summary>
  36. /// <typeparam name="TSource">Source sequence element type.</typeparam>
  37. /// <param name="source">Source sequence.</param>
  38. /// <param name="accumulator">
  39. /// Accumulation function to apply to the current accumulation value and each element of the
  40. /// sequence.
  41. /// </param>
  42. /// <returns>Sequence with all intermediate accumulation values resulting from scanning the sequence.</returns>
  43. public static IEnumerable<TSource> Scan<TSource>(this IEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
  44. {
  45. if (source == null)
  46. {
  47. throw new ArgumentNullException(nameof(source));
  48. }
  49. if (accumulator == null)
  50. {
  51. throw new ArgumentNullException(nameof(accumulator));
  52. }
  53. return ScanCore(source, accumulator);
  54. }
  55. private static IEnumerable<TAccumulate> ScanCore<TSource, TAccumulate>(IEnumerable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
  56. {
  57. var acc = seed;
  58. foreach (var item in source)
  59. {
  60. acc = accumulator(acc, item);
  61. yield return acc;
  62. }
  63. }
  64. private static IEnumerable<TSource> ScanCore<TSource>(IEnumerable<TSource> source, Func<TSource, TSource, TSource> accumulator)
  65. {
  66. var hasSeed = false;
  67. var acc = default(TSource);
  68. foreach (var item in source)
  69. {
  70. if (!hasSeed)
  71. {
  72. hasSeed = true;
  73. acc = item;
  74. continue;
  75. }
  76. acc = accumulator(acc, item);
  77. yield return acc;
  78. }
  79. }
  80. }
  81. }