C#高级置换场景

我试图找出如何找到所有组合给出以下信息:

我从一个JSON数据集开始:

var choices = { 1: {'Q': 100, 'R': 150, 'W' : 250, 'T', 30}, 2: {'Q': 90, 'R': 130, 'W' : 225, 'T', 28}, 3: {'Q': 80, 'R': 110, 'W' : 210, 'T', 25}, 4: {'Q': 70, 'R': 90, 'W' : 180, 'T', 22}, 5: {'Q': 60, 'R': 70, 'W' : 150, 'T', 18}, 6: {'Q': 50, 'R': 50, 'W' : 110, 'T', 15}, 7: {'Q': 40, 'R': 30, 'W' : 80, 'T', 11}, 8: {'Q': 30, 'R': 25, 'W' : 50, 'T', 8}, 9: {'Q': 20, 'R': 10, 'W' : 25, 'T', 5}, 10: {'Q': 10, 'R': 5, 'W' : 15, 'T', 3} }; 

我想弄清楚的是我如何获取这个数据集,并在为每一行选择’Q’,’R’,’W’或’T’元素时生成所有可能的组合。

所以我希望我的最终结果会是这样的

 var allChoices = { 0: {1: {'Q': 100}, 2: {'R': 130}, 3: {'W' : 210}, 4: {'W' : 180}, 5: {'T', 18}, 6: {'R': 50,}, 7: {'Q': 40,}, 8: {'T', 8}, 9: {'R': 10}, 10: {'W' : 15}, }, 1: {...}, ... 1048576: {...} }; 

我使用JSON是因为我认为这是最容易想象的,但是有谁知道如何在c#中实现这一目标?

让我知道,如果这个不够清楚,我很难弄清楚究竟如何提出这个问题。

这是如何使用深度优先递归。 在我的机器上运行大约需要3秒钟。 此外,如果您有5列而不是4列,则将PAIRCOUNT更改为5表示适用于任意大小的配对。只需添加其他对。

  void Main() { var OriginValues = new List>(); OriginValues.Add(new KeyValuePair('Q', 100)); OriginValues.Add(new KeyValuePair('R', 150)); OriginValues.Add(new KeyValuePair('W', 250)); OriginValues.Add(new KeyValuePair('T', 30)); OriginValues.Add(new KeyValuePair('Q', 90)); OriginValues.Add(new KeyValuePair('R', 130)); OriginValues.Add(new KeyValuePair('W', 225)); OriginValues.Add(new KeyValuePair('T', 28)); OriginValues.Add(new KeyValuePair('Q', 80)); OriginValues.Add(new KeyValuePair('R', 110)); OriginValues.Add(new KeyValuePair('W', 210)); OriginValues.Add(new KeyValuePair('T', 25)); ///... and the other 7 var AllPermutation = new List>>(); Recurse(OriginValues, ref AllPermutation); //all results will be in AllPermutation now } const int PAIRCOUNT = 4; void Recurse(List> OriginValues, ref List>> result, List> itemset = null) { itemset = itemset ?? new List>(); var temp = new List>(itemset); if (itemset.Count == OriginValues.Count / PAIRCOUNT) { result.Add(temp); return; } for (int x = 0; x < PAIRCOUNT; x++) { temp.Add(OriginValues[itemset.Count * PAIRCOUNT + x]); Recurse(OriginValues, ref result, temp); temp = new List>(itemset); } } 

这是一个10位数的基数4。

 class Program { static void Main(string[] args) { int baseN = 4; int maxDigits = 10; var max = Math.Pow(baseN, maxDigits); for (int i = 0; i < max; i++) { // each iteration of this loop is another unique permutation var digits = new int[maxDigits]; int value = i; int place = digits.Length - 1; while (value > 0) { int thisdigit = value % baseN; value /= baseN; digits[place--] = thisdigit; } int choice = 0; foreach (var digit in digits) { choice ++; //Console.Write(digit); switch (digit) { case 0: break; //choose Q from choice case 1: break; //choose R from choice case 2: break; //choose W from choice case 3: break; //choose T from choice } } //Console.WriteLine(); // add it to your list of all permutations here } Console.WriteLine("Done") Console.ReadLine(); } } 

您正在寻找的是10个arrays的笛卡尔积(10-ary Cartesian积,因为我认为它更适合调用)。 埃里克·利珀特(Eric Lippert)撰写了一篇很好的(并且相当高级的)关于为这个数目的数组做这个的文章: http ://ericlippert.com/2010/06/28/computing-a-cartesian-product-with-linq/

它的结果是,我认为以下function将满足您的需求:

 static IEnumerable> CartesianProduct(this IEnumerable> sequences) { IEnumerable> emptyProduct = new[] { Enumerable.Empty() }; return sequences.Aggregate( emptyProduct, (accumulator, sequence) => from accseq in accumulator from item in sequence select accseq.Concat(new[] {item})); } 

您的案例中的输入是10个数组的数组。 输出将是一个可以在每个步骤返回十个项目的无数的可数字。 您基本上会迭代该函数的输出以获得所有可能的排列。

看看这个: Linq的组合发电机

没有LINQ的另一种解决方案,假设你每行只做4件事,最简单的方法就是强制它并做嵌套的foreach循环。

 foreach ( choice in allChoices ) { foreach ( choice in allChoices ) { foreach ( choice in allChoices ) { foreach ( choice in allChoices ) { // combine and add to a collection } } } } 

编辑:添加对象以在foreach循环中循环