2013-12-18 70 views
3

想,如果我有這樣的號碼列表,使用LINQ to組號碼

[3, 3, 1, 2, 3, 2] 

,我想他們組合在一起的序列,使得各組的總和小於或等於五,即正確的答案是:

[3], [3, 1], [2,3], [2] 

有沒有一種方法來表達這個使用Linq?

回答

9

容易。

var results = xs.Aggregate<int, List<List<int>>>(
    new List<List<int>> { new List<int>() }, 
    (a, n) => 
    { 
     if (a.Last().Sum() + n > 5) 
     { 
      a.Add(new List<int> { n }); 
     } 
     else 
     { 
      a.Last().Add(n); 
     } 
     return a; 
    }); 

所以,從這個:

var xs = new [] { 3, 3, 1, 2, 3, 2, }; 

我得到這個:

result

+0

+1,非常漂亮的確。 –

+0

非常非常狡猾。我喜歡。唯一潛在的缺點是對於每個前進步驟,Last()列表中的前一個值的重複求和。對於大型目標羣體總和(比如說10000)可能會很慢,但對於目標爲5的情況罰款。 – Baldrick

0

不知道這是任何接近你腦子裏想的是什麼,但讓我們給它一個去

List<int> l = new List<int> { 3, 3, 1, 2, 3, 2 }; 
int[] index = {0}; 
var s = l.Select((k, i) => 
{ 
    if (i < index[0]) 
     return null; 

    int total = 0; 
    return l.Skip(index[0]).TakeWhile(x => 
    { 
     total += x; 
     if (total <= 5) 
      index[0]++; 
     return total <= 5; 
    }); 
}).Where(x => x != null); 

foreach (IEnumerable<int> e in s) 
{ 
    foreach (int i in e) 
    { 
     Console.Write("{0},", i); 
    } 
    Console.WriteLine(); 
} 

我的理由如下,

  1. 我們必須去通過所有的項目,所以選擇。
  2. 我們必須從列表中取項目,直到達到總數,因此TakeWhile
  3. 我們必須跟蹤列表中的位置,因此索引和返回null。

我試着用int index = 0; initialy,但ReSharper的呻吟約訪問修改關閉和recomended其更改爲int[] index = {0};

0

你可以嘗試擴展方法(這樣的事情,你的榜樣測試,但不比這更多的測試!):

public static class Extensions 
{ 
    public static IEnumerable<IEnumerable<int>> GroupsLessThan(this IEnumerable<int> source, int target) 
    { 
     var list = new List<int>(); 
     var runningCount = 0; 
     foreach (var element in source) 
     { 
      if (runningCount + element < target) 
      { 
       list.Add(element); 
       runningCount += element; 
      } 
      else 
      { 
       yield return list; 
       runningCount = element; 
       list = new List<int>{element}; 
      } 
     } 

     if (list.Count > 0) 
     { 
      yield return list; 
     } 
    } 
} 
然後

用法是這樣的:

var array = new int[] { 3, 3, 1, 2, 3, 2 }; 
var list = array.GroupsLessThan(6).ToList();