“N集合中每个集合中的1个项目”

时间:2016-06-02 12:44:54

标签: c# arrays

我有一个嵌套的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来确定索引,但我不确定在{{{{{收藏品已存在。

2 个答案:

答案 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个列表。