使用linq将列表<t>分解为n个长度的<t>列<t> </t> </t>

时间:2011-03-07 03:18:59

标签: .net linq

  

可能重复:
  How can I split an IEnumerable<String> into groups of IEnumerable<string>

我有一个列表,我想分成10组。

如果我有一个对象

List<Person> allPendingPersons 

长度为m。

在LINQ中是否有一种优雅的方法可以将allPendingPersons分解为一个或多个最多包含10个人的List对象?

7 个答案:

答案 0 :(得分:49)

您可以编写自己的扩展方法:

public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> sequence, int size) {
    List<T> partition = new List<T>(size);
    foreach(var item in sequence) {
        partition.Add(item);
        if (partition.Count == size) {
            yield return partition;
            partition = new List<T>(size);
        }
    }
    if (partition.Count > 0)
        yield return partition;
}

我在博客中explored this in more depth

答案 1 :(得分:16)

 var groups = allPendingPersons.Select((p, index) => new {p,index})
                               .GroupBy(a =>a.index/10 );

如果您要处理IGrouping<,>。如果您正在寻找List&gt;回来你可以尝试

var listOfLists = allPendingPersons.Select((p, index) => new {p, index})
    .GroupBy(a => a.index/10)
    .Select((grp => grp.Select(g => g.p).ToList()))
    .ToList();

答案 2 :(得分:7)

Reactive Extensions for .NET (Rx)有一个扩展方法可以完全符合您的要求:

var buffered = allPendingPersons.BufferWithCount(10);

如果你想使用LINQ这样做,你可以这样做:

var buffered =
    allPendingPersons
        .Select((p, i) => new { Group = i / 10, Person = p })
        .GroupBy(x => x.Group, x => x.Person)
        .Select(g => g.ToArray());

答案 3 :(得分:4)

答案 4 :(得分:2)

这不是最有效的技术,但这将生成IEnumerable<IEnumerable<Person>>序列,每个内部序列包含十个元素:

var query = allPendingPersons.Select((x, i) => new { Value = x, Group = i / 10 })
                             .GroupBy(x => x.Group,
                                      (k, g) => g.Select(x => x.Value));

如果结果确实需要是列表列表而不是简单序列,那么您可以通过添加几个List<List<Person>>调用来创建ToList

var query = allPendingPersons.Select((x, i) => new { Value = x, Group = i / 10 })
                             .GroupBy(x => x.Group,
                                      (k, g) => g.Select(x => x.Value).ToList())
                             .ToList();

答案 5 :(得分:0)

尝试使用迭代器块:

public static IEnumerable<List<Person>> AsGroups(this List<Person> persons)
{
    var buf = new List<Person>(10);
    for (int i = 0; i<persons.Count i++;)
    {
        buf.Add(persons[i]);
        if (i%10 == 0 && buf.Count > 0)
        {
           yield return buf;
           buf = new List<Person>(10);
        }
    }
    yield return buf;
 }

答案 6 :(得分:0)

  

LINQ中是否有一种优雅的方式

elegant way效率不高。这是一种更高效的方式......

    public static List<List<T>> Chunk<T>(
      this List<T> theList,
      int chunkSize
    )
    {
        if (!theList.Any())
        {
            return new List<List<T>>();
        }

        List<List<T>> result = new List<List<T>>();
        List<T> currentList = new List<T>();
        result.Add(currentList);

        int i = 0;
        foreach(T item in theList)
        {
            if (i >= chunkSize)
            {
                i = 0;
                currentList = new List<T>();
                result.Add(currentList);
            }
            i += 1;
            currentList.Add(item);
        }
        return result;
    }