swift 从多个数组中拾取元素

hxzsmxv2  于 2023-03-28  发布在  Swift
关注(0)|答案(2)|浏览(140)

如何在Swift中从多个数组中获取所有可能的元素组合?
下面是一个例子:

let myArray = [[2,3,4],
[1,2,3,4,5],
[1,2],
]

myArray元素的数量可能会有所不同,其中的数组也是如此。
代码应该输出一个数组,每次从每个数组中选择一个元素,似乎是基本的,但我现在看不到它

yh2wf1be

yh2wf1be1#

使用来自https://stackoverflow.com/a/20049365/1187415的想法,这可以在Swift中完成

// Append all elements of a2 to each element of a1
func combihelper(a1 : [[Int]], a2 : [Int]) -> [[Int]] {
    var result = [[Int]]()
    for elem1 in a1 {
        for elem2 in a2 {
            result.append(elem1 + [elem2])
        }
    }
    return result
}

func combinations(array : [[Int]]) -> [[Int]] {
    // Start with the "empty combination" , then successively
    // add combinations with each row of array:
    var result : [[Int]] = [[]]
    for row in array {
        result = combihelper(result, row)
    }
    return result
}

最后一个函数可以更快地写成

func combinations(array : [[Int]]) -> [[Int]] {
    return reduce(array, [[]]) { combihelper($0, $1) }
}

示例:

let myArray = [[1],
    [2,3,4],
    [5,6],
]
let result = combinations(myArray)
println(result)
// [[1, 2, 5], [1, 2, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6]]

(If你的输入不限于整数,你可以在上面的函数中用Any替换Int
更新Swift 3并作为泛型函数,以便它可以与任何元素类型一起使用:

func combihelper<T>(a1 : [[T]], a2 : [T]) -> [[T]] {
    var result = [[T]]()
    for elem1 in a1 {
        for elem2 in a2 {
            result.append(elem1 + [elem2])
        }
    }
    return result
}

func combinations<T>(of array: [[T]]) -> [[T]] {
    return array.reduce([[]]) { combihelper(a1: $0, a2: $1) }
}

let myArray = [[1],
               [2,3,4],
               [5,6],
]

let result = combinations(of: myArray)
print(result) // [[1, 2, 5], [1, 2, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6]]
soat7uwm

soat7uwm2#

我希望这是一个扩展,所以这里是Martin R的优秀答案的翻译,作为Collection的扩展和一些测试应该涵盖它:

extension Collection where Element: Collection {
    typealias Output = [[Element.Element]]
    
    func combinations() -> Output {
        guard !isEmpty else { return [] }
        
        return reduce([[]], combinations)
    }
    
    private func combinations(_ c1: Output, _ c2: Element) -> Output {
        c1.reduce(into: Output()) { combinations, elem1 in
            c2.forEach { elem2 in
                combinations.append(elem1 + [elem2])
            }
        }
    }
}

final class CombinationsTests: XCTestCase {
    func assertCombinations(of a: [[Int]], expected: [[Int]], line: UInt = #line) {
        XCTAssertEqual(expected, a.combinations(), line: line)
    }
    
    func testCombinations() {
        assertCombinations(of: [], expected: [])
        assertCombinations(of: [[]], expected: [])
        assertCombinations(of: [[], []], expected: [])
        assertCombinations(of: [[1]], expected: [[1]])
        assertCombinations(of: [[1, 2]], expected: [[1], [2]])
        assertCombinations(of: [[1], [2]], expected: [[1, 2]])
        assertCombinations(of: [[1], [2], [3]], expected: [[1, 2, 3]])
        assertCombinations(of: [[1, 2], [3]], expected: [[1, 3], [2, 3]])
        assertCombinations(of: [[1, 2], [3, 4]], expected: [[1, 3], [1, 4], [2, 3], [2, 4]])
    }
}

相关问题