我的问题是这样的:
我有几个列表需要排列,但列表编号不可知。并且每个列表中的每个元素编号也是不可知的。我想遍历所有列表元素组合,例如1)从列表1中选择A,从列表2中选择A,从列表3中选择A; 2) 从列表 1 中选择 A,从列表 2 中选择 A,从列表 3 中选择 B ...对于所有排列。
我使用嵌套的for循环来遍历,就像我有两个列表,那么:
for (int i = 0; i < list[0].EnergyParameters.ListEnergyLevelCandidates.Count; i++)
{
for (int j = 0; j < list[1].EnergyParameters.ListEnergyLevelCandidates.Count; j++)
{
// Do sth
}
}
如果我有三个列表,那么:
for (int i = 0; i < list[0].EnergyParameters.ListEnergyLevelCandidates.Count; i++)
{
for (int j = 0; j < list[1].EnergyParameters.ListEnergyLevelCandidates.Count; j++)
{
for (int k = 0; k < list[2].EnergyParameters.ListEnergyLevelCandidates.Count; k++)
{
// Do sth
}
}
}
因为列表编号不可知,所以嵌套编号也不可知,也就是说,我不知道需要写多少层for循环。
在这种情况下,如何编写动态for循环级别的代码?我不想为 10 个列表编写 10 个循环。
如果您不知道有多少个列表,则不要编写嵌套循环:而是编写递归。在调用的每个级别,您循环一个列表,如下所示:
void AllCombos(List<string>[] lists, int level, string[] current) {
if (level == lists.Length) {
// Do somthing; items of current[] contain elements of the combination
} else {
foreach (var s in lists[level]) {
current[level] = s;
AllCombos(lists, level+1, current);
}
}
}
拨打
AllCombos
如下:
var lists = new List<string>[10];
for (int i = 0 ; i != 10 ; i++) {
lists[i] = PopulateMyList(i);
}
string[] current = new string[lists.Length];
AllCombos(lists, 0, current);
有时,您需要迭代未知数量的 for 或 foreach 循环。例如,假设我们有以下字符串集合:
var data = new List<List<string>>{
new List<string>{"red", "green", "blue"},
new List<string>{"apple", "banana", "peach", "mellon"},
new List<string>{"one", "two"}
};
private static void Main()
{
var data = new List<List<string>>
{
new List<string> {"red", "green", "blue"},
new List<string> {"apple", "banana", "peach", "mellon"},
new List<string> {"one", "two"}
};
foreach (var item in IterateDynamicLoop(data).Select(x => string.Join("-", x)))
Console.WriteLine(item);
Console.ReadLine();
}
public static IEnumerable<IEnumerable<T>> IterateDynamicLoop<T>(IList<List<T>> data)
{
var count = data.Count;
var loopIndex = count - 1;
var counters = new int[count];
var bounds = data.Select(x => x.Count).ToArray();
do
{
yield return Enumerable.Range(0, count).Select(x => data[x][counters[x]]);
} while (IncrementLoopState(counters, bounds, ref loopIndex));
}
private static bool IncrementLoopState(IList<int> counters, IList<int> bounds, ref int loopIndex)
{
if (loopIndex < 0)
return false;
counters[loopIndex] = counters[loopIndex] + 1;
var result = true;
if (counters[loopIndex] >= bounds[loopIndex])
{
counters[loopIndex] = 0;
loopIndex--;
result = IncrementLoopState(counters, bounds, ref loopIndex);
loopIndex++;
}
return result;
}