Vince O'Sullivan Vince O'Sullivan - 1 year ago 87
Swift Question

Swift List Product

Given two lists in Swift:

let rows = ["a", "b", "c"]
let cols = ["1", "2", "3"]

Is it possible to combine them using list comprehension to produce the following:

squares = ["a1", "a2", "a3", "b1", "b2", "b3", "c1", "c2", "c3"]

Obviously, it can be done using a "for loop" and similar constructs, but I'm specifically for a list comprehension based solution. I know Swift can do some list comprehension (e.g. let evens = Array(filter(1..<10) { $0 % 2 == 0 }) ) but can't figure out if it can do something similar to the following piece of Haskell:

let squares = [ r ++ c | r <- rows, c <- cols]

Answer Source

A possible solution (now updated for Swift 2):

let rows = ["a", "b", "c"]
let cols = ["1", "2", "3"]

let squares = rows.flatMap {
    row in {
        col in
        row + col
// [a1, a2, a3, b1, b2, b3, c1, c2, c3]

The inner map() maps the cols array to an array with the row number prepended to each entry. The outer flatMap() maps the rows array to an array of arrays (one for each row) and flattens the result.

Slightly more general, one could define the "product" of two sequences as an array of tuples (pairs) with all combinations:

func product<S : SequenceType, T : SequenceType>(lseq : S, _ rseq : T) -> [(S.Generator.Element, T.Generator.Element)] {
    return lseq.flatMap { left in { right in
            (left, right)

and then use it as

let squares = product(rows, cols).map(+)