Anton
Anton

Reputation: 339

swift 4 combinations func

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

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

What's the best solution to write the code in one func and more swifty?

Upvotes: 0

Views: 312

Answers (2)

Leo Dabus
Leo Dabus

Reputation: 236360

If all you want is to combine both methods into a single one just change a1 to $0 and a2 to $1:

func combinations<T>(of array: [[T]]) -> [[T]] {
    return array.reduce([[]]) {
        var x = [[T]]()
        for elem1 in $0 {
            for elem2 in $1 {
                x.append(elem1 + [elem2])
            }
        }
        return x
    }
}

let multi = [[1,2,3,4,5],[1,2,3,4,5,6,7,8,9,0]]
combinations(of: multi)  // [[1, 1], [1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [1, 7], [1, 8], [1, 9], [1, 0], [2, 1], [2, 2], [2, 3], [2, 4], [2, 5], [2, 6], [2, 7], [2, 8], [2, 9], [2, 0], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7], [3, 8], [3, 9], [3, 0], [4, 1], [4, 2], [4, 3], [4, 4], [4, 5], [4, 6], [4, 7], [4, 8], [4, 9], [4, 0], [5, 1], [5, 2], [5, 3], [5, 4], [5, 5], [5, 6], [5, 7], [5, 8], [5, 9], [5, 0]]

Extending Collection, constraining the element to RangeReplaceableCollection and using higher-order functions we can came up with:

extension Collection where Element: RangeReplaceableCollection  {
    func combinations() -> [Element] {
        reduce([.init()]) { result, element in
            result.flatMap { elements in
                element.map { elements + CollectionOfOne($0) }
            }
        }
    }
}

let strings = ["12345","1234567890"]
strings.combinations()  // ["11", "12", "13", "14", "15", "16", "17", "18", "19", "10", "21", "22", "23", "24", "25", "26", "27", "28", "29", "20", "31", "32", "33", "34", "35", "36", "37", "38", "39", "30", "41", "42", "43", "44", "45", "46", "47", "48", "49", "40", "51", "52", "53", "54", "55", "56", "57", "58", "59", "50"]

Upvotes: 3

Alain T.
Alain T.

Reputation: 42143

You could also do it without any for loops:

func combinations<T>(of array: [[T]]) -> [[T]]
{
   return array.reduce([[]]){ c,a in c.flatMap{ e in a.map{e + [$0] } } }
}

Upvotes: 1

Related Questions