鉴于我有一个这样的整数列表:
List<int> items = new List<int> {200, 100, 50, 20, 10, 5, 2, 1};
并且假设我有一个数字,比方说13,我如何从列表中找到使用LINQ(或任何其他方式)加起来为13的数字。该列表始终按降序排列。
例如:13 = 10 + 2+ 1,因此linq操作会返回一个包含10,2和1的整数列表。
如果我们无法像24的情况那样找到完整匹配,则可以生成异常。
努力:
[Test]
public void Should_find_subset()
{
var items = new List<int>() {200, 100, 50, 20, 10, 5, 2, 1};
var find = 13;
var result = new List<int>();
var subset = new List<int>();
bool found = false;
foreach (var item in items)
{
if (item == find)
{
result.Add(item);
found = true;
}
if (item < find)
{
subset.Add(item);
found = subset.Sum() == find;
}
if (found)
break;
}
}
谢谢,
-Mike
答案 0 :(得分:4)
如果我听到组合,我建议这个项目:Permutations, Combinations, and Variations
这是有效的代码:
List<int> items = new List<int> { 200, 100, 50, 20, 10, 5, 2, 1 };
var allMatchingCombos = new List<IList<int>>();
for (int i = 1; i < items.Count; i++)
{
IEnumerable<IList<int>> matchingCombos = new Combinations<int>(items, i, GenerateOption.WithoutRepetition)
.Where(c => c.Sum() == 13);
allMatchingCombos.AddRange(matchingCombos);
}
foreach(var combo in allMatchingCombos)
Console.WriteLine(string.Join(",", combo));
输出:10,2,1
编辑:由于您已明确要求LINQ,因此这是一个完整的LINQified方法:
List<IList<int>> allMatchingCombos = Enumerable.Range(1, items.Count)
.SelectMany(i => new Combinations<int>(items, i, GenerateOption.WithoutRepetition)
.Where(c => c.Sum() == 13)
.ToList())
.ToList();
答案 1 :(得分:3)
使用Aggregate
的简单而低效的方法:
List<int> items = new List<int> {200, 100, 50, 20, 10, 5, 2, 1};
var target = 373;
var result = items.Aggregate(new List<int>(), (acc, curr) =>
{
if (acc.Sum() + curr <= target)
acc.Add(curr);
return acc;
});
if(result.Sum() != target)
throw new Exception(); // whatever
<强>结果:强>
我应该注意,这种简单的方法并不适用于所有情况。例如。列表是68,50,20,目标是70.这将导致错误,而不是50,20。
处理此类案件的另一种低效方法:
List<int> items = new List<int> {68, 50, 20};
var target = 70;
var result = new List<int>();
while(result.Sum() != target && items.Any())
{
result = new List<int>();
foreach (var item in items)
if (result.Sum() + item <= target)
result.Add(item);
if(result.Sum() != target)
items.Remove(result.Last());
}
if(result.Sum() != target)
throw new Exception(); // whatever, no solution found
<强>结果:强>
使用大型输入列表可能会很慢。