2011-03-07 47 views

回答

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

如果你想處理IGrouping<,>。如果您正在尋找名單>回你可以嘗試

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

不是最高效的,GroupBy會緩衝所有元素並構建查找。因此,內存+ CPU開銷+不是蒸汽解決方案 – 2015-04-22 23:52:43

46

您可以編寫自己的擴展方法:

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

稍微好做:'分區=新名單(大小);' – nawfal 2013-02-18 13:55:08

+0

@nawfal:你說的沒錯;固定。 – SLaks 2013-02-18 21:50:36

+0

這太好了!我直接在需要採取行動的項目清單上使用它。 foreach(var in senders.Partition(threshold)){handleBatch(b); } 簡單而優雅,謝謝! – 2014-05-01 19:30:09

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(); 
+1

您可以通過編寫'x => x.Value'而不是'(k,g)=> g.Select(x => x)來簡化您的第一個版本。值)'。 – 2011-03-07 03:40:13

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

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()); 
4
+0

+1 MoreLink的'Batch',[見源代碼](https://github.com/morelinq/MoreLINQ/blob/master/MoreLinq/Batch.cs) – lagerone 2016-09-06 08:26:20

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; 
    } 
+1

您可以比編寫迭代器更高效。看到我的答案。 – SLaks 2011-03-08 16:26:17