我一直在用一种方法把集合分成几批形成这个答案--。https:/stackoverflow.coma175988781012739。:
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int size) {
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());
}
迭代处理以下结果时 Batch<T>
会得到预期的收藏数量,但当调用 Count
或 ToList
报道了外链长度。
var collection = new int[10];
var count = 0;
foreach(var batch in collection.Batch(2))
++count;
Assert.AreEqual(5, count); // Passes
// But
Assert.AreEqual(5, collection.Batch(2).Count()); // Fails
Assert.AreEqual(5, collection.Batch(2).ToList().Count); // Fails
这是怎么做到的,有办法解决吗?
您的 TakeIEnumerator<T>
方法取决于枚举器的位置(source
),因此,它本身......是依赖于时间的。如果结果是通过先整理 "外部 "结果来迭代的,即
var batches = source.Batch(24).ToList();
// then iterate in any way
那么根据定义。source
用完了,你会得到N个项目,在 batches
,其中 N
是指从 source
而所有的批次都会是空的,因为那里有 没有数据了. 然而,如果结果是先迭代深度,即
foreach (var batch in source) {
foreach (var item in batch) {...}
}
那么你看的就是打开的光标。最终,这种方法本质上是脆弱和危险的。IMO,你的批处理方法应该创建计算数据的缓冲区,也许是个 List<T>
或类似。这将分配,但:会很可靠。例如:
private static IEnumerable<T> TakeIEnumerator<T>(IEnumerator<T> source, int size) {
var buffer = new List<T>(size);
int i = 0;
do buffer.Add(source.Current);
while (++i < size && source.MoveNext())
return buffer;
}