// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT License. // See the LICENSE file in the project root for more information. using System.Collections.Generic; namespace System.Linq { public static partial class EnumerableEx { /// /// Generates a sequence of non-overlapping adjacent buffers over the source sequence. /// /// Source sequence element type. /// Source sequence. /// Number of elements for allocated buffers. /// Sequence of buffers containing source sequence elements. public static IEnumerable> Buffer(this IEnumerable source, int count) { if (source == null) throw new ArgumentNullException(nameof(source)); if (count <= 0) throw new ArgumentOutOfRangeException(nameof(count)); return BufferCore(source, count, count); } /// /// Generates a sequence of buffers over the source sequence, with specified length and possible overlap. /// /// Source sequence element type. /// Source sequence. /// Number of elements for allocated buffers. /// Number of elements to skip between the start of consecutive buffers. /// Sequence of buffers containing source sequence elements. public static IEnumerable> Buffer(this IEnumerable source, int count, int skip) { if (source == null) throw new ArgumentNullException(nameof(source)); if (count <= 0) throw new ArgumentOutOfRangeException(nameof(count)); if (skip <= 0) throw new ArgumentOutOfRangeException(nameof(skip)); return BufferCore(source, count, skip); } private static IEnumerable> BufferCore(IEnumerable source, int count, int skip) { var buffers = new Queue>(); var i = 0; foreach (var item in source) { if (i % skip == 0) { buffers.Enqueue(new List(count)); } foreach (var buffer in buffers) { buffer.Add(item); } if (buffers.Count > 0 && buffers.Peek().Count == count) { yield return buffers.Dequeue(); } i++; } while (buffers.Count > 0) { yield return buffers.Dequeue(); } } } }