Buffer.cs 3.2 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;
  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 non-overlapping adjacent buffers over the source sequence.
  14. /// </summary>
  15. /// <typeparam name="TSource">Source sequence element type.</typeparam>
  16. /// <param name="source">Source sequence.</param>
  17. /// <param name="count">Number of elements for allocated buffers.</param>
  18. /// <returns>Sequence of buffers containing source sequence elements.</returns>
  19. public static IEnumerable<IList<TSource>> Buffer<TSource>(this IEnumerable<TSource> source, int count)
  20. {
  21. if (source == null)
  22. throw new ArgumentNullException(nameof(source));
  23. if (count <= 0)
  24. throw new ArgumentOutOfRangeException(nameof(count));
  25. return source.Buffer_(count, count);
  26. }
  27. /// <summary>
  28. /// Generates a sequence of buffers over the source sequence, with specified length and possible overlap.
  29. /// </summary>
  30. /// <typeparam name="TSource">Source sequence element type.</typeparam>
  31. /// <param name="source">Source sequence.</param>
  32. /// <param name="count">Number of elements for allocated buffers.</param>
  33. /// <param name="skip">Number of elements to skip between the start of consecutive buffers.</param>
  34. /// <returns>Sequence of buffers containing source sequence elements.</returns>
  35. public static IEnumerable<IList<TSource>> Buffer<TSource>(this IEnumerable<TSource> source, int count, int skip)
  36. {
  37. if (source == null)
  38. throw new ArgumentNullException(nameof(source));
  39. if (count <= 0)
  40. throw new ArgumentOutOfRangeException(nameof(count));
  41. if (skip <= 0)
  42. throw new ArgumentOutOfRangeException(nameof(skip));
  43. return source.Buffer_(count, skip);
  44. }
  45. private static IEnumerable<IList<TSource>> Buffer_<TSource>(this IEnumerable<TSource> source, int count, int skip)
  46. {
  47. var buffers = new Queue<IList<TSource>>();
  48. var i = 0;
  49. foreach (var item in source)
  50. {
  51. if (i%skip == 0)
  52. buffers.Enqueue(new List<TSource>(count));
  53. foreach (var buffer in buffers)
  54. buffer.Add(item);
  55. if (buffers.Count > 0 && buffers.Peek()
  56. .Count == count)
  57. yield return buffers.Dequeue();
  58. i++;
  59. }
  60. while (buffers.Count > 0)
  61. yield return buffers.Dequeue();
  62. }
  63. }
  64. /// <summary>
  65. /// Represents a buffer exposing a shared view over an underlying enumerable sequence.
  66. /// </summary>
  67. /// <typeparam name="T">Element type.</typeparam>
  68. public interface IBuffer<out T> : IEnumerable<T>, IDisposable
  69. {
  70. }
  71. }