Ich versuche, die IEnumerable<T>
in gleichen Teilmengen zu Charge und kam über folgende Lösungen:IEnumerable batching Diskrepanz in Count() Wert
MoreLinq Nuget Bibliothek Batch, deren Umsetzung detailliert hier:
MoreLinq - Batch , Einfügen Quellcode unter:
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); } }
Eine weitere optimale Lösung ist auf der folgenden l verfügbar Tinte (mehr Speicher effizient):
IEnumerable Batching, code Einfügen Quelle unter:
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()); } }
Beide Lösungen bieten, die das Endergebnis als IEnumerable<IEnumerable<T>>
.
Ich finde die Diskrepanz in der folgenden Code:
var result = Fetch IEnumerable<IEnumerable<T>>
aus beiden Verfahren vorgeschlagen oben
result.Count()
, führt zu unterschiedlichem Ergebnis seiner korrekten für MoreLinq Batch, aber nicht korrekt für andere, auch wenn das Ergebnis korrekt ist und für beide gleich
das follwing Beispiel vor:
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
Auch wenn das Batching-Ergebnis korrekt ist, wenn wir ToList()
tun, ist der Fehler, da wir immer noch mit dem Speicher-Stream in der zweiten Methode und Speicher nicht zugeordnet ist, aber immer noch falsches Ergebnis nicht der Fall sein wird, Alle Ansichten/Vorschläge
Ich denke, dass Sie den Code teilen müssen, den Sie gerade ausführen. – buffjape
Wenn Sie die Frage sorgfältig betrachten, ist der Code genau da, bis Sie den Quellcode aus den entsprechenden Links kopieren möchten. Was Teil Ihrer Meinung nach fehlt/unklar, beide die Batching-Mechanismen sind IEnumerable Erweiterungen –
@ Veverke Keine Batch-Arbeiten, das ist der interessante Teil, wie ich erwähnt, zeigt das korrekte Ergebnis auf 'ToList()', aber 'Count () 'ist nicht korrekt. Falscher Code ist auch die Stapelüberlauf-Frageantwort, nicht verwandt mit MoreLinq, ich bevorzuge diese Antwort wegen seiner Optimierung aber kann den Grund für das Problem nicht aufzeigen –