Scan.cs 3.5 KB

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