如何迭代不同长度的列表来查找所有排列?

这个不应该太难,但我的思想似乎是堆栈溢出(huehue)。 我有一系列的列表,我想找到他们可以订购的所有排列。所有列表都有不同的长度。

例如:

清单1:1

清单2:1,2

所有排列都是:

1,1

1,2

在我的情况下,我不会切换数字。 (例如2,1)最简单的方法是什么?

我不能说以下是最简单的方法,但IMO是最有效的方式。 它基本上是我对锯齿状数组中每个组合的回答的一般化版本:

public static class Algorithms { public static IEnumerable GenerateCombinations(this IReadOnlyList> input) { var result = new T[input.Count]; var indices = new int[input.Count]; for (int pos = 0, index = 0; ;) { for (; pos < result.Length; pos++, index = 0) { indices[pos] = index; result[pos] = input[pos][index]; } yield return result; do { if (pos == 0) yield break; index = indices[--pos] + 1; } while (index >= input[pos].Count); } } } 

您可以在链接的答案中看到解释(很快就会模拟嵌套循环)。 此外,由于性能原因,它产生内部缓冲区而无需克隆它,如果要存储结果以供以后处理,则需要克隆它。

样品用法:

 var list1 = new List { 1 }; var list2 = new List { 1, 2 }; var lists = new[] { list1, list2 }; // Non caching usage foreach (var combination in lists.GenerateCombinations()) { // do something with the combination } // Caching usage var combinations = lists.GenerateCombinations().Select(c => c.ToList()).ToList(); 

更新: GenerateCombinations是一个标准的C# 迭代器方法,实现基本上模拟N嵌套循环(其中Ninput.Count ),如下所示(伪代码):

for(int i 0 = 0; i 0 0 ++)
for(int i 1 = 0; i 1 1 ++)
for(int i 2 = 0; i 2 2 ++)

for(int i N-1 = 0; i N-1 N-1 ++)
yield {input [0] [i 0 ],input [1] [i 1 ],input [2] [i 2 ],…,input [N-1] [i N-1 ]}

或以不同方式显示:

 for (indices[0] = 0; indices[0] < input[0].Count; indices[0]++) { result[0] = input[0][indices[0]]; for (indices[1] = 0; indices[1] < input[1].Count; indices[1]++) { result[1] = input[1][indices[1]]; // ... for (indices[N-1] = 0; indices[N-1] < input[N-1].Count; indices[N-1]++) { result[N-1] = input[N-1][indices[N-1]]; yield return result; } } } 

嵌套循环:

 List listA = (whatever), listB = (whatever); var answers = new List>; for(int a in listA) for(int b in listB) answers.add(Tuple.create(a,b)); // do whatever with answers 

试试这个:

 Func, IEnumerable> combine = null; combine = xs => xs.Skip(1).Any() ? xs.First().SelectMany(x => combine(xs.Skip(1)), (x, y) => String.Format("{0}{1}", x, y)) : xs.First().Select(x => x.ToString()); var strings = new [] { "AB", "12", "$%" }; foreach (var x in combine(strings)) { Console.WriteLine(x); } 

这给了我:

 A1 $
 A1%
 A2 $
 A2%
 B1 $
 B1%
 B2 $
 B2%