快速修剪并创建有效的数据组合

时间:2013-08-09 15:20:02

标签: c# algorithm

我真的很难解决一个问题,我需要将可用场景“修剪”为用户定义为有效的场景。下面是我试图在.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

我尝试过的东西都是小型套装,但如果我在组合中有很多级别和大差距,那么在我深入到水平之前我不能修剪有效组合,我遇到了重大的性能问题。我显然没有错误地解决这个问题。

非常感谢有关解决问题的任何其他意见或建议。

1 个答案:

答案 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