如何找到多个列表元素的所有可能组合?

时间:2019-05-16 22:20:19

标签: swift arraylist

我需要找到列表列表中包含的多个列表的所有组合。例如:

鉴于[[1, 2, 3], [4, 5], [6]],我需要获取(顺序不重要)

[[1, 4, 6], [1, 5, 6], [2, 4, 6], [2, 5, 6], [3, 4, 6], [3, 5, 6]]

如果我提前知道列表的原始列表中包含多少个列表(并且这个数目足够小),那么很容易进行嵌套嵌套以生成组合。但是我的情况是我不知道这一点。我将如何生成此列表?

尽管我正在使用Swift,但我认为这个问题比这更普遍。如果有特定的Swift方法可以做到这一点,对我有用。

1 个答案:

答案 0 :(得分:0)

您可以通过乘以子数组的大小来找到组合的预期数量。因此[[1, 2, 3], [4, 5], [6]]将生成3 * 2 * 1 = 6组合。

这是一个通用函数,它将组合多个数组以创建每个原始子数组中元素的所有组合的数组。

通过从原始数组中删除第一个子数组,然后在递归调用自身之前将这些元素添加到部分列表中来建立部分列表,从而实现递归工作。

当最终用一个空列表调用Combine时,它将返回现已完成的部分列表。

返回的列表收集在变量result中,并从combine返回。

// combine elements from the sub-arrays of lists
// partial holds the partial results as the combinations are built up
// partial has a default value of empty array for the initial call

func combine<T>(lists: [[T]], partial: [T] = []) -> [[T]] {
    // print("combine(lists: \(lists), partial: \(partial))")
    if lists.isEmpty {
        // recursive base case: lists is now empty, so partial
        // is complete, so return it in an enclosing array
        // print("... returning \([partial])")
        return [partial]
    } else {
        // make lists mutable so that we can remove the first sub-array
        var lists = lists

        // remove the first sub-array from lists which is now shorter
        let first = lists.removeFirst()

        // create an array to hold all of the combinations
        var result = [[T]]()

        // take each element from the first sub-array, append it to
        // the partial result, and call combine to continue the
        // process.  Take the results returned from combine and append
        // those to the result array.
        for n in first {
            result += combine(lists: lists, partial: partial + [n])
        }

        // Return the results
        // print("... returning \(result)")
        return result
    }
}

测试:

let result = combine(lists: [[1, 2, 3], [4, 5], [6]])
print(result)

输出:

[[1, 4, 6], [1, 5, 6], [2, 4, 6], [2, 5, 6], [3, 4, 6], [3, 5, 6]]

如果您取消注释三个print语句,则可以了解其工作原理:

combine(lists: [[1, 2, 3], [4, 5], [6]], partial: [])
combine(lists: [[4, 5], [6]], partial: [1])
combine(lists: [[6]], partial: [1, 4])
combine(lists: [], partial: [1, 4, 6])
... returning [[1, 4, 6]]
... returning [[1, 4, 6]]
combine(lists: [[6]], partial: [1, 5])
combine(lists: [], partial: [1, 5, 6])
... returning [[1, 5, 6]]
... returning [[1, 5, 6]]
... returning [[1, 4, 6], [1, 5, 6]]
combine(lists: [[4, 5], [6]], partial: [2])
combine(lists: [[6]], partial: [2, 4])
combine(lists: [], partial: [2, 4, 6])
... returning [[2, 4, 6]]
... returning [[2, 4, 6]]
combine(lists: [[6]], partial: [2, 5])
combine(lists: [], partial: [2, 5, 6])
... returning [[2, 5, 6]]
... returning [[2, 5, 6]]
... returning [[2, 4, 6], [2, 5, 6]]
combine(lists: [[4, 5], [6]], partial: [3])
combine(lists: [[6]], partial: [3, 4])
combine(lists: [], partial: [3, 4, 6])
... returning [[3, 4, 6]]
... returning [[3, 4, 6]]
combine(lists: [[6]], partial: [3, 5])
combine(lists: [], partial: [3, 5, 6])
... returning [[3, 5, 6]]
... returning [[3, 5, 6]]
... returning [[3, 4, 6], [3, 5, 6]]
... returning [[1, 4, 6], [1, 5, 6], [2, 4, 6], [2, 5, 6], [3, 4, 6], [3, 5, 6]]