假设我有一个这样的数字列表,
[3, 3, 1, 2, 3, 2]
我希望按顺序将它们组合在一起,使每组的总和小于或等于5,即正确的答案是:
[3], [3, 1], [2,3], [2]
有没有办法用Linq来表达这个?
答案 0 :(得分: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, };
我明白了:
答案 1 :(得分: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();
}
我的推理如下,
我尝试使用int index = 0;
初始化,但Resharper呻吟着访问修改后的闭包,并建议将其更改为int[] index = {0};
答案 2 :(得分: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();