是否有任何方法可以将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]

我还需要结果列表的大小是这个函数的参数。


当前回答

我们发现David B的解决方案效果最好。但我们把它改成了一个更普遍的解决方案:

list.GroupBy(item => item.SomeProperty) 
   .Select(group => new List<T>(group)) 
   .ToArray();

其他回答

这个怎么样?

var input = new List<string> { "a", "g", "e", "w", "p", "s", "q", "f", "x", "y", "i", "m", "c" };
var k = 3

var res = Enumerable.Range(0, (input.Count - 1) / k + 1)
                    .Select(i => input.GetRange(i * k, Math.Min(k, input.Count - i * k)))
                    .ToList();

据我所知,GetRange()与所获取的项目数量是线性的。所以这应该表现得很好。

我们可以改进@JaredPar的解决方案来做真正的惰性求值。我们使用GroupAdjacentBy方法生成一组具有相同键的连续元素:

sequence
.Select((x, i) => new { Value = x, Index = i })
.GroupAdjacentBy(x=>x.Index/3)
.Select(g=>g.Select(x=>x.Value))

因为基团是一个接一个地产生的,所以这个解决方案对长序列或无限序列有效。

对于任何对打包/维护解决方案感兴趣的人来说,MoreLINQ库提供了符合您所请求行为的批处理扩展方法:

IEnumerable<char> source = "Example string";
IEnumerable<IEnumerable<char>> chunksOfThreeChars = source.Batch(3);

批处理实现类似于Cameron MacFarland的答案,在返回之前添加了用于转换块/批处理的重载,并且性能相当好。

如果列表的类型为system.collections.generic,则可以使用“CopyTo”方法将数组中的元素复制到其他子数组中。您可以指定开始元素和要复制的元素数量。

你也可以对你的原始列表做3个克隆,并在每个列表上使用“RemoveRange”将列表缩小到你想要的大小。

或者只是创建一个helper方法来为您做这件事。

我发现这个小片段做得很好。

public static IEnumerable<List<T>> Chunked<T>(this List<T> source, int chunkSize)
{
    var offset = 0;

    while (offset < source.Count)
    {
        yield return source.GetRange(offset, Math.Min(source.Count - offset, chunkSize));
        offset += chunkSize;
    }
}