Higher-order functions on arrays

I want to learn more about functional programming. I decided to start with an "easy" example: getting the Cartesian product of two arrays, as in this code:


let xArray = [1, 2, 3]
let yArray = [4, 5, 6]
var pairs: [(Int, Int)] = []
for x in xArray {
  for y in yArray {
    pairs.append((x, y))
  }
}


Now, many hours later, I still haven't figured out how to do this in a functional way. Perhaps I should stick to declarative programming.

Answered by OOPer in 373953022

How is this?

let xArray = [1, 2, 3]
let yArray = [4, 5, 6]
let product = xArray.map { xElem in yArray.map {yElem in (xElem, yElem)}}.flatMap{$0}
print(product) //->[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]

I am not sure to understand what you are really looking for.


Are you looking for a notation "a la map()" as

(array1, array2).cartesian


Are you looking for a recursive construction of cartesian ?


Do you know zip function ?

let xArray = [1, 2, 3]
let yArray = [4, 5, 6]
let zArray = zip(xArray, yArray)

for z in zArray { print(z) }

yields

(1, 4)

(2, 5)

(3, 6)


It will even work if not same soze arrays.

With

let xArray = [1, 2, 3]
let yArray = [4, 5, 6, 7]
let zArray = zip(xArray, yArray)

for z in zArray { print(z) }

you get

(1, 4)

(2, 5)

(3, 6)

I want to get the array [(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)].

You could also define an operator for cartesian product:


infix operator ⊗  

extension Array where Element : Any {
    static func ⊗(left:[Element], right:[Element]) -> [(Element, Element)] {
       
        var pairs: [(Element, Element)] = []
        for x in left {
            for y in right {
                pairs.append((x, y))
            }
        }
        return pairs
    }
}

let cartArray = xArray ⊗ yArray
print(cartArray)


gives

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


It will work for any values:


let x2Array = [1, 2, 3]
let y2Array = ["A", "B", 6] as [Any]
let cartArray = x2Array ⊗ y2Array
print(cartArray)

[(1, "A"), (1, "B"), (1, 6), (2, "A"), (2, "B"), (2, 6), (3, "A"), (3, "B"), (3, 6)]


Note:

That can probably be written with map(), but it rapidly becomes hard to read…

Accepted Answer

How is this?

let xArray = [1, 2, 3]
let yArray = [4, 5, 6]
let product = xArray.map { xElem in yArray.map {yElem in (xElem, yElem)}}.flatMap{$0}
print(product) //->[(1, 4), (1, 5), (1, 6), (2, 4), (2, 5), (2, 6), (3, 4), (3, 5), (3, 6)]

Nice.

Beautiful! I'd gotten the first part of that, but didn't realize that flatMap would combine the three arrays.

Higher-order functions on arrays
 
 
Q