-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4c9eaeb
commit 6581fe6
Showing
3 changed files
with
125 additions
and
73 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace Lemonad.Enumerable { | ||
public static partial class Enumerable { | ||
/// <summary> | ||
/// Chunks the elements of a sequence according to a amount and creates a result value from each group and its max capacity. | ||
/// </summary> | ||
/// <param name="source">An <see cref="IEnumerable{T}"/> whose elements to chunk.</param> | ||
/// <param name="size">The max capacity for each chunk.</param> | ||
/// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam> | ||
/// <returns>An <see cref="IEnumerable{T}"/> with chunks.</returns> | ||
/// <exception cref="ArgumentNullException">When <paramref name="source"/> is null.</exception> | ||
/// <exception cref="ArgumentException">When <paramref name="size"/> is below 1.</exception> | ||
public static IEnumerable<IEnumerable<TSource>> ChunkBy<TSource>(this IEnumerable<TSource> source, int size) { | ||
if (source == null) { | ||
throw new ArgumentNullException(nameof(source)); | ||
} | ||
|
||
if (size < 1) { | ||
throw new ArgumentException($"Parameter: '{nameof(size)}' ({size}) can not be below 1."); | ||
} | ||
|
||
return CreateChunks(source, size); | ||
} | ||
|
||
private static IEnumerable<IEnumerable<TSource>> CreateChunks<TSource>(IEnumerable<TSource> source, int size) { | ||
var index = 0; | ||
var elements = new TSource[size]; | ||
var count = 0; | ||
|
||
foreach (var element in source) { | ||
elements[count] = element; | ||
checked { | ||
index++; | ||
} | ||
|
||
count = index % size; | ||
if (count == 0) { | ||
yield return elements; | ||
elements = new TSource[size]; | ||
} | ||
} | ||
|
||
// Avoids returning empty chunks. | ||
if (count > 0) { | ||
yield return new ArraySegment<TSource>(elements, 0, count); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,74 +1,51 @@ | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace Lemonad.Enumerable { | ||
public static partial class Enumerable { | ||
/// <summary> | ||
/// Chunks the elements of a sequence according to a amount and creates a result value from each group and its max capacity. | ||
/// </summary> | ||
/// <param name="source">An <see cref="IEnumerable{T}"/> whose elements to chunk.</param> | ||
/// <param name="count">The max capacity for each <see cref="IChunk{T}"/>.</param> | ||
/// <param name="size">The max capacity for each chunk.</param> | ||
/// <typeparam name="TSource">The type of the elements in <paramref name="source"/>.</typeparam> | ||
/// <returns>The type of the elements <paramref name="source"/>.</returns> | ||
/// <returns>An <see cref="IEnumerable{T}"/> with chunks.</returns> | ||
/// <exception cref="ArgumentNullException">When <paramref name="source"/> is null.</exception> | ||
/// <exception cref="ArgumentException">When <paramref name="count"/> is below 1.</exception> | ||
public static IEnumerable<IChunk<TSource>> ChunkBy<TSource>(this IEnumerable<TSource> source, int count) { | ||
/// <exception cref="ArgumentException">When <paramref name="size"/> is below 1.</exception> | ||
public static IEnumerable<IEnumerable<TSource>> ChunkBy<TSource>(this IEnumerable<TSource> source, int size) { | ||
if (source == null) { | ||
throw new ArgumentNullException(nameof(source)); | ||
} | ||
|
||
if (count < 1) { | ||
throw new ArgumentException($"Parameter: '{nameof(count)}' ({count}) can not be below 1."); | ||
if (size < 1) { | ||
throw new ArgumentException($"Parameter: '{nameof(size)}' ({size}) can not be below 1."); | ||
} | ||
|
||
foreach (IEnumerable<TSource> enumerable in CreateChunks(source, count)) { | ||
yield return new Chunk<TSource>(enumerable, count); | ||
} | ||
return CreateChunks(source, size); | ||
} | ||
|
||
private static IEnumerable<IEnumerable<TSource>> CreateChunks<TSource>(IEnumerable<TSource> source, int count) { | ||
private static IEnumerable<IEnumerable<TSource>> CreateChunks<TSource>(IEnumerable<TSource> source, int size) { | ||
var index = 0; | ||
var elements = new Queue<TSource>(); | ||
var elements = new TSource[size]; | ||
var count = 0; | ||
|
||
foreach (var element in source) { | ||
elements.Enqueue(element); | ||
elements[count] = element; | ||
checked { | ||
index++; | ||
} | ||
if (index % count == 0) { | ||
|
||
count = index % size; | ||
if (count == 0) { | ||
yield return elements; | ||
elements = new Queue<TSource>(); | ||
elements = new TSource[size]; | ||
} | ||
} | ||
|
||
yield return elements; | ||
} | ||
} | ||
|
||
public sealed class Chunk<T> : IChunk<T> { | ||
private readonly IEnumerable<T> _chunk; | ||
|
||
public Chunk(IEnumerable<T> chunk, int count) { | ||
_chunk = chunk; | ||
MaxCount = count; | ||
// Avoids returning empty chunks. | ||
if (count > 0) { | ||
yield return new ArraySegment<TSource>(elements, 0, count); | ||
} | ||
} | ||
|
||
public IEnumerator<T> GetEnumerator() => _chunk.GetEnumerator(); | ||
|
||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | ||
|
||
/// <summary> | ||
/// The max amount of allowed elements in <see cref="IChunk{T}"/>. | ||
/// </summary> | ||
public int MaxCount { get; } | ||
} | ||
|
||
/// <summary> | ||
/// Represents a collection of elements that have a common max count. | ||
/// </summary> | ||
/// <typeparam name="T">The type of the elements.</typeparam> | ||
public interface IChunk<out T> : IEnumerable<T> { | ||
int MaxCount { get; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters