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.
Vous n'avez pas besoin d'écrire de code. Utilisez PlusLINQ La méthode Batch, qui permet de regrouper la séquence source en lots de taille variable (MoreLINQ est disponible sous la forme d'un paquet NuGet que vous pouvez installer) :
int size = 10;
var batches = sequence.Batch(size);
Qui est mis en œuvre comme :
public static IEnumerable<IEnumerable<TSource>> Batch<TSource>(
this IEnumerable<TSource> source, int size)
{
TSource[] bucket = null;
var count = 0;
foreach (var item in source)
{
if (bucket == null)
bucket = new TSource[size];
bucket[count++] = item;
if (count != size)
continue;
yield return bucket;
bucket = null;
count = 0;
}
if (bucket != null && count > 0)
yield return bucket.Take(count).ToArray();
}
public static class MyExtensions
{
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> items,
int maxItems)
{
return items.Select((item, inx) => new { item, inx })
.GroupBy(x => x.inx / maxItems)
.Select(g => g.Select(x => x.item));
}
}
et l'usage serait :
List<int> list = new List<int>() { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
foreach(var batch in list.Batch(3))
{
Console.WriteLine(String.Join(",",batch));
}
SORTIE :
0,1,2
3,4,5
6,7,8
9
Si vous commencez par sequence
défini comme un IEnumerable<T>
et vous savez qu'il peut être énuméré plusieurs fois en toute sécurité (par exemple, parce qu'il s'agit d'un tableau ou d'une liste), vous pouvez utiliser ce modèle simple pour traiter les éléments par lots :
while (sequence.Any())
{
var batch = sequence.Take(10);
sequence = sequence.Skip(10);
// do whatever you need to do with each batch here
}
Un site Enumerable.Chunk()
a été ajoutée à .NET 6.0.
Ejemplo:
var list = new List<int> { 1, 2, 3, 4, 5, 6, 7 };
var chunks = list.Chunk(3);
// returns { { 1, 2, 3 }, { 4, 5, 6 }, { 7 } }
Pour ceux qui ne peuvent pas faire de mise à niveau, la source est disponible sur GitHub .
Il s'agit d'une implémentation entièrement paresseuse, à faible coût et à fonction unique de Batch qui ne fait pas d'accumulation. Basée sur (et corrigeant les problèmes de) l'implémentation de Nick Whaley. solution avec l'aide d'EricRoller.
L'itération provient directement de l'IEnumerable sous-jacent. Les éléments doivent donc être énumérés dans un ordre strict, et on ne peut y accéder plus d'une fois. Si certains éléments ne sont pas consommés dans une boucle interne, ils sont rejetés (et essayer d'y accéder à nouveau par le biais d'un itérateur sauvegardé lèvera l'interdiction d'accès aux éléments). InvalidOperationException: Enumeration already finished.
).
Vous pouvez tester un échantillon complet à l'adresse suivante .NET Fiddle .
public static class BatchLinq
{
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int size)
{
if (size <= 0)
throw new ArgumentOutOfRangeException("size", "Must be greater than zero.");
using (var enumerator = source.GetEnumerator())
while (enumerator.MoveNext())
{
int i = 0;
// Batch is a local function closing over `i` and `enumerator` that
// executes the inner batch enumeration
IEnumerable<T> Batch()
{
do yield return enumerator.Current;
while (++i < size && enumerator.MoveNext());
}
yield return Batch();
while (++i < size && enumerator.MoveNext()); // discard skipped items
}
}
}
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.