我真的很难解决一个问题,我需要将可用场景“修剪”为用户定义为有效的场景。下面是我试图在.Net(C#)中解决的问题的一个小例子。给定下面显示的级别/值,用户可以选择只有几个有效组合,但如果您认为低于30-40级别的数据而不是我所显示的5级,您可以看到我的困境。我可能需要经历数百万到数十亿的NOT VALID组合才能获得有效组合。有些情况下,级别中的所有值都适用,有些只有用户指定的组合。
当前级别/数据值:
用户说有效组合是:
*Notice all from level 4 are valid
Receiver -> Sony -> 500 -999 -> Retail
Receiver -> Sony -> 1000 - Up -> Retail
从给定的5个级别的信息中得出的结果:
Receiver -> Sony -> 500-999 -> Open -Box -> Retail
Receiver -> Sony -> 500-999 -> New -> Retail
Receiver -> Sony -> 1000-Up -> Open -Box -> Retail
Receiver -> Sony -> 1000-Up -> New -> Retail
我尝试过的东西都是小型套装,但如果我在组合中有很多级别和大差距,那么在我深入到水平之前我不能修剪有效组合,我遇到了重大的性能问题。我显然没有错误地解决这个问题。
非常感谢有关解决问题的任何其他意见或建议。
答案 0 :(得分:3)
假设您能够将输入解析为N个不同的集合,每个集合包含特定级别的有效值,问题就是找到这N个集合的笛卡尔积。
Eric Lippert已经a blog post在其中完成了一个解决方案的创建,以便在编译时获得许多序列未知的笛卡尔积。从该帖子的末尾开始的代码是:
static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences)
{
IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() };
return sequences.Aggregate(
emptyProduct,
(accumulator, sequence) =>
from accseq in accumulator
from item in sequence
select accseq.Concat(new[] {item}));
}
在示例输入中使用此代码:
var validValues = new string[][]{
new string[] {"Receiver"},
new string[] {"Sony"},
new string[] {"500 -999","1000 - Up"},
new string[] {"Open -Box","New "},
new string[] {"Retail"},
};
foreach(var combination in validValues.CartesianProduct())
Console.WriteLine(string.Join(" ", combination));
提供输出:
Receiver Sony 500 -999 Open -Box Retail Receiver Sony 500 -999 New Retail Receiver Sony 1000 - Up Open -Box Retail Receiver Sony 1000 - Up New Retail