是否有任何方法可以将List<SomeObject>分离为SomeObject的几个单独的列表,使用项目索引作为每个分割的分隔符?
让我举个例子:
我有一个List<SomeObject>,我需要一个List<List<SomeObject>>或List<SomeObject>[],这样每个结果列表将包含一组原始列表的3个项目(依次)。
eg.:
原始列表:[a, g, e, w, p, s, q, f, x, y, i, m, c]
结果列表:[a、g e], [w、p, s], [q, f, x]、[y,我,m], [c]
我还需要结果列表的大小是这个函数的参数。
山姆·萨弗伦的做法是如此的做作。
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> source, int size)
{
if (source == null) throw new ArgumentNullException(nameof(source));
if (size <= 0) throw new ArgumentOutOfRangeException(nameof(size), "Size must be greater than zero.");
return BatchImpl(source, size).TakeWhile(x => x.Any());
}
static IEnumerable<IEnumerable<T>> BatchImpl<T>(this IEnumerable<T> source, int size)
{
var values = new List<T>();
var group = 1;
var disposed = false;
var e = source.GetEnumerator();
try
{
while (!disposed)
{
yield return GetBatch(e, values, group, size, () => { e.Dispose(); disposed = true; });
group++;
}
}
finally
{
if (!disposed)
e.Dispose();
}
}
static IEnumerable<T> GetBatch<T>(IEnumerator<T> e, List<T> values, int group, int size, Action dispose)
{
var min = (group - 1) * size + 1;
var max = group * size;
var hasValue = false;
while (values.Count < min && e.MoveNext())
{
values.Add(e.Current);
}
for (var i = min; i <= max; i++)
{
if (i <= values.Count)
{
hasValue = true;
}
else if (hasValue = e.MoveNext())
{
values.Add(e.Current);
}
else
{
dispose();
}
if (hasValue)
yield return values[i - 1];
else
yield break;
}
}
}