我有一个整数列表,它只包含4个数字,如图所示,我需要写一个Linq表达式,它提取一个整数数组列表,只包含加法等于“total”的数字,听起来很简单,但这里很棘手第一部分我只想要具有最小计数的整数数组,所以如果total = 4,那么我想要int [] {4}但是我想要int [] {2,2}或int [] {1,3}等,如果总数是5那么我想要int [] {1,4},int [] {4,1},int [] {2,3},int [] {3,2},也许这可能是完成了一堆if语句,但我希望那里有一个强大的linq表达式。
var total = 5;
var numList = new List<int>() { 1, 2, 3, 4 };
答案 0 :(得分:0)
您必须从一个相当复杂的代码开始,以生成源数组的所有组合。像这样:
public IEnumerable<IEnumerable<T>> Combinations<T>(IEnumerable<T> source)
{
if (!source.Any())
{
return Enumerable.Empty<IEnumerable<T>>();
}
else if (!source.Skip(1).Any())
{
return new [] { source, source.Take(0) };
}
else
{
return Combinations(source.Skip(1))
.SelectMany(xs => new [] { source.Take(1).Concat(xs), xs });
}
}
现在剩下的很简单。就这样做:
var query =
(
from xs in Combinations(new [] { 1, 2, 3, 4, })
where xs.Sum() == 5
orderby xs.Count()
group xs by xs.Count()
)
.Take(1)
.SelectMany(xs => xs);
我按预期得到了以下结果:
答案 1 :(得分:0)
好的,这是一个函数
/// <summary>
/// Gets integer combinations between 0 and an exclusive upper bound.
/// </summary>
/// <param name="l">The length of the combination.</param>
/// <param name="n">The exclusive upper bound.</param>
/// <returns>
/// All combinations of the specified length in the specified range.
/// </returns>
public static IEnumerable<IEnumerable<int>> Combinations(int l, int n)
{
var result = new int[l];
var stack = new Stack<int>();
stack.Push(0);
while (stack.Count > 0)
{
var index = stack.Count - 1;
var value = stack.Pop();
while (value < n)
{
result[index++] = value++;
stack.Push(value);
if (index == 1)
{
yield return result;
break;
}
}
}
}
你可以在这样的扩展方法中使用它。
public static IEnumerable<IEnumerable<T>> CombinationsIncreasingLength<T>(
this IEnumerable<T> source)
{
var sourceList = source.ToList();
if (sourceList.Count < 2)
{
return new[] { sourceList };
}
return
Enumerable.Range(1, sourceList.Count)
.SelectMany(l => Combinations(l, sourceList.Count)
.Select(indices => indices.Select(i => sourceList[i])));
}
这将为您提供source
增加长度的所有组合。
因此,要找到与值完全相加的最短组合,您可以这样做。
numList.CombinationsIncreasingLength().First(c => c.Sum() == total);