Quelqu'un peut-il suggérer un moyen de créer des lots d'une certaine taille en linq ?
Idéalement, je voudrais pouvoir effectuer des opérations par tranches d'une certaine quantité configurable.
Quelqu'un peut-il suggérer un moyen de créer des lots d'une certaine taille en linq ?
Idéalement, je voudrais pouvoir effectuer des opérations par tranches d'une certaine quantité configurable.
Une version facile à utiliser et à comprendre.
public static List<List<T>> chunkList<T>(List<T> listToChunk, int batchSize)
{
List<List<T>> batches = new List<List<T>>();
if (listToChunk.Count == 0) return batches;
bool moreRecords = true;
int fromRecord = 0;
int countRange = 0;
if (listToChunk.Count >= batchSize)
{
countRange = batchSize;
}
else
{
countRange = listToChunk.Count;
}
while (moreRecords)
{
List<T> batch = listToChunk.GetRange(fromRecord, countRange);
batches.Add(batch);
if ((fromRecord + batchSize) >= listToChunk.Count)
{
moreRecords = false;
}
fromRecord = fromRecord + batch.Count;
if ((fromRecord + batchSize) > listToChunk.Count)
{
countRange = listToChunk.Count - fromRecord;
}
else
{
countRange = batchSize;
}
}
return batches;
}
Voici une implémentation qui utilise l'itération Async en C# via IAsyncEnumerable
- https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/generate-consume-asynchronous-stream
public static class EnumerableExtensions
{
/// <summary>
/// Chunks a sequence into a sub-sequences each containing maxItemsPerChunk, except for the last
/// which will contain any items left over.
///
/// NOTE: this implements a streaming implementation via <seealso cref="IAsyncEnumerable{T}"/>.
/// </summary>
public static async IAsyncEnumerable<IEnumerable<T>> ChunkAsync<T>(this IAsyncEnumerable<T> sequence, int maxItemsPerChunk)
{
if (sequence == null) throw new ArgumentNullException(nameof(sequence));
if (maxItemsPerChunk <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxItemsPerChunk), $"{nameof(maxItemsPerChunk)} must be greater than 0");
}
var chunk = new List<T>(maxItemsPerChunk);
await foreach (var item in sequence)
{
chunk.Add(item);
if (chunk.Count == maxItemsPerChunk)
{
yield return chunk.ToArray();
chunk.Clear();
}
}
// return the "crumbs" that
// didn't make it into a full chunk
if (chunk.Count > 0)
{
yield return chunk.ToArray();
}
}
/// <summary>
/// Chunks a sequence into a sub-sequences each containing maxItemsPerChunk, except for the last
/// which will contain any items left over.
/// </summary>
public static IEnumerable<IEnumerable<T>> Chunk<T>(this IEnumerable<T> sequence, int maxItemsPerChunk)
{
if (sequence == null) throw new ArgumentNullException(nameof(sequence));
if (maxItemsPerChunk <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxItemsPerChunk), $"{nameof(maxItemsPerChunk)} must be greater than 0");
}
var chunk = new List<T>(maxItemsPerChunk);
foreach (var item in sequence)
{
chunk.Add(item);
if (chunk.Count == maxItemsPerChunk)
{
yield return chunk.ToArray();
chunk.Clear();
}
}
// return the "crumbs" that
// didn't make it into a full chunk
if (chunk.Count > 0)
{
yield return chunk.ToArray();
}
}
}
Je sais que tout le monde a utilisé des systèmes complexes pour faire ce travail, et je ne comprends vraiment pas pourquoi. Take and skip permettra toutes ces opérations en utilisant le select commun avec Func<TSource,Int32,TResult>
fonction de transformation. Comme :
public IEnumerable<IEnumerable<T>> Buffer<T>(IEnumerable<T> source, int size)=>
source.Select((item, index) => source.Skip(size * index).Take(size)).TakeWhile(bucket => bucket.Any());
Une autre façon de procéder à la mise en lots :
public static class Extensions
{
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
yield return func(v0, v1);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
yield return func(v0, v1, v2);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
yield return func(v0, v1, v2, v3);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v5 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4, v5);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v5 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v6 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4, v5, v6);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v5 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v6 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v7 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4, v5, v6, v7);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v5 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v6 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v7 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v8 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4, v5, v6, v7, v8);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v5 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v6 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v7 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v8 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v9 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v5 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v6 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v7 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v8 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v9 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v10 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v5 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v6 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v7 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v8 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v9 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v10 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v11 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v5 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v6 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v7 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v8 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v9 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v10 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v11 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v12 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v5 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v6 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v7 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v8 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v9 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v10 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v11 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v12 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v13 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v5 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v6 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v7 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v8 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v9 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v10 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v11 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v12 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v13 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v14 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14);
}
}
}
public static IEnumerable<TOut> Batch<T, TOut>(this IEnumerable<T> source, Func<T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, T, TOut> func)
{
using (var enumerator = source.GetEnumerator())
{
while (true)
{
bool state;
state = enumerator.MoveNext(); if (!state) break; var v0 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v1 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v2 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v3 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v4 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v5 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v6 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v7 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v8 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v9 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v10 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v11 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v12 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v13 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v14 = enumerator.Current;
state = enumerator.MoveNext(); if (!state) break; var v15 = enumerator.Current;
yield return func(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15);
}
}
}
}
Voici un exemple d'utilisation :
using System;
using System.Linq;
namespace TestProgram
{
class Program
{
static void Main(string[] args)
{
foreach (var item in Enumerable.Range(0, 12).ToArray().Batch((R, X1, Y1, X2, Y2) => (R, X1, Y1, X2, Y2)))
{
Console.WriteLine($"{item.R}, {item.X1}, {item.Y1}, {item.X2}, {item.Y2}");
}
}
}
}
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.