Je suis en train de lots de la IEnumerable<T>
dans des sous-ensembles égaux et est tombé sur des solutions suivantes:différence de traitement par lots IEnumerable valeur Count()
MoreLinq bibliothèque Nuget lots, dont la mise en œuvre est détaillée ici:
MoreLinq - Batch , coller le code source sous:
public static IEnumerable<TResult> Batch<TSource, TResult>(this IEnumerable<TSource> source, int size, Func<IEnumerable<TSource>, TResult> resultSelector) { if (source == null) throw new ArgumentNullException(nameof(source)); if (size <= 0) throw new ArgumentOutOfRangeException(nameof(size)); if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); return BatchImpl(source, size, resultSelector); } private static IEnumerable<TResult> BatchImpl<TSource, TResult> (this IEnumerable<TSource> source, int size,Func<IEnumerable<TSource>, TResult> resultSelector) { Debug.Assert(source != null); Debug.Assert(size > 0); Debug.Assert(resultSelector != null); TSource[] bucket = null; var count = 0; foreach (var item in source) { if (bucket == null) { bucket = new TSource[size]; } bucket[count++] = item; // The bucket is fully buffered before it's yielded if (count != size) { continue; } // Select is necessary so bucket contents are streamed too yield return resultSelector(bucket); bucket = null; count = 0; } // Return the last bucket with all remaining elements if (bucket != null && count > 0) { Array.Resize(ref bucket, count); yield return resultSelector(bucket); } }
Une autre solution optimale est disponible sur le suivant l encre (plus efficace de la mémoire):
IEnumerable Batching, coller le code source sous:
public static class BatchLinq { public static IEnumerable<IEnumerable<T>> CustomBatch<T>(this IEnumerable<T> source, int size) { if (size <= 0) throw new ArgumentOutOfRangeException("size", "Must be greater than zero."); using (IEnumerator<T> enumerator = source.GetEnumerator()) while (enumerator.MoveNext()) yield return TakeIEnumerator(enumerator, size); } private static IEnumerable<T> TakeIEnumerator<T>(IEnumerator<T> source, int size) { int i = 0; do yield return source.Current; while (++i < size && source.MoveNext()); } }
Les deux solutions fournissent le résultat final comme IEnumerable<IEnumerable<T>>
.
je trouve la différence dans le morceau de code suivant:
var result = Fetch IEnumerable<IEnumerable<T>>
de méthode soit suggérée ci-dessus
result.Count()
, conduit à un résultat différent, son correct pour MoreLinq lot, mais pas correct pour un autre, même lorsque le résultat est correct et même pour les deux
Prenons l'exemple follwing:
IEnumerable<int> arr = new int[10] {1,2,3,4,5,6,7,8,9,10};
For a Partition size 3
arr.Batch(3).Count(), will provide result 4 which is correct
arr.BatchLinq(3).Count(), will provide result 10 which is incorrect
Même lorsque le résultat de traitement par lots fourni est correct, lorsque nous faisons ToList()
, est l'erreur puisque nous traitons toujours le flux de mémoire dans la deuxième méthode et la mémoire n'est pas allouée, mais le résultat incorrect ne sera pas le cas, suggestions
Je pense que vous devez partager le code que vous exécutez. – buffjape
Si vous regardez la question attentivement, le code est là, jusqu'à et sauf si vous préférez copier le code source des liens respectifs aussi. Quelle partie pensez-vous est manquant/pas clair, les deux mécanismes de traitement par lots sont extensions IEnumerable –
@Veverke Aucun lot fonctionne, c'est la partie intéressante, comme je l'ai mentionné, il montre le résultat correct sur faire ToList() ', mais' Count () 'n'est pas correct. Aussi le code incorrect est la réponse à la question de dépassement de pile, non liée à MoreLinq, je préfère cette réponse en raison de son optimisation mais je ne peux pas indiquer la raison du problème –