我有一个嵌套的List<List<int>>
数据结构,我想迭代最近int
个元素的每个可能组合,例如每个组合中的每个组合中只有一个值{{1} }} 用来。例如,请考虑以下嵌套列表:
List<int>
前几种组合会产生:
var listOfLists = new List<List<int>>()
{
new List<int>() { 1, 2, 3, 4, 9 },
new List<int>() { 0, 3, 4, 5 },
new List<int>() { 1, 6 }
};
我怎么能做到这一点?
我最初的方法是对索引进行排列,但内部1 0 1 // Indices: 0 0 0
1 0 6 // Indices: 0 0 1
1 3 1 // Indices: 0 1 0
1 3 6 // Indices: 0 1 1
2 0 1 // Indices: 1 0 0
2 0 6 // Indices: 1 0 1
2 3 1 // Indices: 1 1 0
...
列表的长度不一定相等。我能想到的另一种方法是将每个内部List<int>
的长度相乘,然后使用模数和除法运算符结合Math.Floor来确定索引,但我不确定在{{{{{收藏品已存在。
答案 0 :(得分:1)
我已经回答了几个类似的问题,这些问题基本上都使用了同一算法的变体。以下是Looking at each combination in jagged array的修改版本:
public static class Algorithms
{
public static IEnumerable<T[]> GetCombinations<T>(this IReadOnlyList<IReadOnlyList<T>> input)
{
var result = new T[input.Count];
var indices = new int[result.Length];
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);
}
}
}
注意,为了不进行分配,上面的方法产生一个相同的数组实例。如果您只想使用foreach
循环或LINQ查询计算或处理它而不存储结果,这是完美的。例如:
foreach (var combination in listOfLists.GetCombinations())
{
// do something with the combination
}
如果您确实需要存储结果,则可以始终使用ToList
:
var allCombinations = listOfLists.GetCombinations().Select(c => c.ToList()).ToList();
答案 1 :(得分:0)
如何使用 LINQ ?
var listOfLists = new List<List<int>>()
{
new List<int>() { 1, 2, 3, 4, 9 },
new List<int>() { 0, 3, 4, 5 },
new List<int>() { 1, 6 }
};
var result = from l in listOfLists[0]
from y in listOfLists[1]
from z in listOfLists[2]
select new List<int>()
{
l,
y,
z
};
这当然只适用于此特定列表,因为列表中有3个列表。