【发布时间】:2020-07-31 16:33:10
【问题描述】:
我正在尝试找出一种有效的方法来创建一个方法,该方法采用包含多个顺序整数列表的字典(每个列表必须从 0 或更高开始,以 100 或更低结束,但确切的数字可能会有所不同)和返回一个字典列表,其中包含所有数字之和为 100 的所有排列。
例如,对于 4 个类别:10 + 20 + 10 + 60 = 100
结果列表中的每个字典都应该为每个键存储一个整数值。
这是我想出的一些代码来说明我的问题:
using System;
using System.Collections.Generic;
using System.Linq;
namespace recursiveTest
{
class Program
{
static void Main(string[] args)
{
Dictionary<string, List<int>> data = new Dictionary<string, List<int>>();
data.Add("A", Enumerable.Range(0, 100).ToList());
data.Add("B", Enumerable.Range(0, 100).ToList());
data.Add("C", Enumerable.Range(0, 100).ToList());
data.Add("D", Enumerable.Range(0, 100).ToList());
// I would like to add a few entries more...
List<Dictionary<string, int>> permutations = new List<Dictionary<string, int>>();
foreach (var a in data["A"])
{
foreach (var b in data["B"])
{
foreach (var c in data["C"])
{
foreach (var d in data["D"])
{
if (a + b + c + d == 100)
{
var current = new Dictionary<string, int>()
{
["A"] = a,
["B"] = b,
["C"] = c,
["D"] = d,
};
permutations.Add(current);
}
}
}
}
}
Console.WriteLine($"Found (foreach): {permutations.Count()}");
Console.ReadKey();
}
}
}
使用 LINQ 的替代方法:
List<Dictionary<string, int>> permutations2 = (from a in data["A"]
from b in data["B"]
from c in data["C"]
from d in data["D"]
where a + b + c + d == 100
let current = new Dictionary<string, int>()
{
["A"] = a,
["B"] = b,
["C"] = c,
["D"] = d,
}
select current).ToList();
Console.WriteLine($"Found (LINQ): {permutations2.Count()}");
Console.ReadKey();
在类别(字典键)和数字开始增长之前,这并不是一项非常复杂的任务......由于字典键(类别)的数量可能会有所不同,这似乎是递归的潜在候选者,但是我无法让它工作。这两个版本有一些明显的缺点:
- 一旦项目和/或类别的数量增加,性能就会突然下降。
- 箭头形状的代码似乎是灾难的秘诀。
- 它会尝试遍历所有可能的组合,而实际上只有少数是有用的(总和为 100 的组合)。
用简短易读的代码和良好的性能实现预期结果的最佳方法是什么?
在尝试找出这 100 个总和值时,有没有办法过滤掉不必要的循环?
编辑: 为了澄清起见,我的想法是能够定义一个带有这样签名的方法:
private static List<Dictionary<string, int>> GetValidPermutations(Dictionary<string, List<int>> data)
然后这样称呼它:
List<Dictionary<string, int>> permutations = GetValidPermutations(data);
【问题讨论】:
-
所以你想从每个列表中只取一个数字作为总和,对吗?
-
对。每个类别都有一个列表,因此输入是字符串键(类别)和 List
值的字典。该方法应返回一个字典列表,其中每个字典都应具有相同的一组键(类别)和一个单独的 int 值。此输出列表中每个字典的值的总和应始终为 100。
标签: c# performance linq recursion readability