想,如果我有這樣的號碼列表,使用LINQ to組號碼
[3, 3, 1, 2, 3, 2]
,我想他們組合在一起的序列,使得各組的總和小於或等於五,即正確的答案是:
[3], [3, 1], [2,3], [2]
有沒有一種方法來表達這個使用Linq?
想,如果我有這樣的號碼列表,使用LINQ to組號碼
[3, 3, 1, 2, 3, 2]
,我想他們組合在一起的序列,使得各組的總和小於或等於五,即正確的答案是:
[3], [3, 1], [2,3], [2]
有沒有一種方法來表達這個使用Linq?
容易。
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, };
我得到這個:
不知道這是任何接近你腦子裏想的是什麼,但讓我們給它一個去
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();
}
我的理由如下,
我試着用int index = 0;
initialy,但ReSharper的呻吟約訪問修改關閉和recomended其更改爲int[] index = {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();
+1,非常漂亮的確。 –
非常非常狡猾。我喜歡。唯一潛在的缺點是對於每個前進步驟,Last()列表中的前一個值的重複求和。對於大型目標羣體總和(比如說10000)可能會很慢,但對於目標爲5的情況罰款。 – Baldrick