Lazily enumerate source enumerable

Don't consume with ToArray() before iterating and yielding results back. This decreases allocations
This commit is contained in:
Oliver Booth 2021-07-20 17:15:10 +01:00
parent 35a9b31be7
commit d6e8471239
No known key found for this signature in database
GPG Key ID: A4AC17007530E9B4
1 changed files with 24 additions and 11 deletions

View File

@ -1,6 +1,5 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace X10D namespace X10D
{ {
@ -23,24 +22,38 @@ namespace X10D
} }
/// <summary> /// <summary>
/// Splits <paramref name="value" /> into chunks of size <paramref name="chunkSize" />. /// Splits <paramref name="source" /> into chunks of size <paramref name="chunkSize" />.
/// </summary> /// </summary>
/// <typeparam name="T">Any type.</typeparam> /// <typeparam name="T">Any type.</typeparam>
/// <param name="value">The collection to split.</param> /// <param name="source">The collection to split.</param>
/// <param name="chunkSize">The maximum length of the nested collection.</param> /// <param name="chunkSize">The maximum length of the nested collection.</param>
/// <returns> /// <returns>
/// An <see cref="IEnumerable{T}" /> containing an <see cref="IEnumerable{T}" /> of <typeparamref name="T" /> /// An <see cref="IEnumerable{T}" /> containing an <see cref="IEnumerable{T}" /> of <typeparamref name="T" />
/// whose lengths are no greater than <paramref name="chunkSize" />. /// whose lengths are no greater than <paramref name="chunkSize" />.
/// </returns> /// </returns>
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> value, int chunkSize) public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int chunkSize)
{ {
var enumerable = value.ToArray(); if (source is null)
var count = enumerable.LongLength;
chunkSize = chunkSize.Clamp(1, enumerable.Length);
for (var i = 0; i < (int)(count / chunkSize); i++)
{ {
yield return enumerable.Skip(i * chunkSize).Take(chunkSize); throw new ArgumentNullException(nameof(source));
}
var buffer = new List<T>(chunkSize);
foreach (var item in source)
{
buffer.Add(item);
if (buffer.Count >= chunkSize)
{
yield return buffer;
buffer.Clear();
}
}
if (buffer.Count > 0)
{
yield return buffer;
} }
} }
} }