Using "Map" in Swift To Create Superset of Two Arrays Using "Map" in Swift To Create Superset of Two Arrays xcode xcode

Using "Map" in Swift To Create Superset of Two Arrays


You can use zip(_:_:) before map:

let a = ["a", "b", "c", "d", "e"]let b = [1, 2, 3, 4, 5]let result = zip(a, b).map { $0 + String($1) }print(result) // => ["a1", "b2", "c3", "d4", "e5"]

You can try this code here.

zip(_:_:) produces a custom Zip2Sequence, which has a special implmentation of the SequenceType protocol, so that it iterates pairs made from the two source collections.


Actually you can do it using only map!

If the two sequences have the same size just enumerate and map:

let result = letterArray.enumerate().map { $0.element + String(numberArray[$0.index]) }

If you're not sure which one is larger and you wanna trim using the smaller just flatMap the undesired values away:

let result = letterArray.enumerate().flatMap {    guard numberArray.count > $0.index else { return .None }    return $0.element + String(numberArray[$0.index])} as [String]


#1. Using zip(_:_:) to combine elements of an array of String with elements of an array of Int into a new array of String

With Swift 3, Swift Standard Library provides zip(_:_:) function. zip(_:_:) has the following declaration:

func zip<Sequence1, Sequence2>(_ sequence1: Sequence1, _ sequence2: Sequence2) -> Zip2Sequence<Sequence1, Sequence2> where Sequence1 : Sequence, Sequence2 : Sequence

Creates a sequence of pairs built out of two underlying sequences.


In order to get a new array from a Zip2Sequence instance, you can use Zip2Sequence's map(_:) method. The Playground code below that uses map(_:) combines your letter and number elements into a new array of String:

let letterArray = ["a", "b", "c", "d", "e"]let numberArray = [1, 2, 3, 4, 5, 6, 7]let zipSequence = zip(letterArray, numberArray)let finalArray = zipSequence.map({ (tuple: (letter: String, number: Int)) -> String in    return tuple.letter + String(tuple.number)})print(finalArray) // prints ["a1", "b2", "c3", "d4", "e5"]

You can refactor the previous code with a much concise style:

let letterArray = ["a", "b", "c", "d", "e"]let numberArray = [1, 2, 3, 4, 5, 6, 7]let finalArray = zip(letterArray, numberArray).map { $0.0 + String($0.1) }print(finalArray) // prints ["a1", "b2", "c3", "d4", "e5"]

As an alternative to map(_:), you can use Zip2Sequence's reduce(_:_:) method:

let letterArray = ["a", "b", "c", "d", "e"]let numberArray = [1, 2, 3, 4, 5, 6, 7]let zipSequence = zip(letterArray, numberArray)let finalArray = zipSequence.reduce([]) { (partialResult: [String], tuple: (letter: String, number: Int)) -> [String] in    return partialResult + [tuple.letter + String(tuple.number)]}print(finalArray) // prints ["a1", "b2", "c3", "d4", "e5"]

#2. Using an Array extension custom method to combine elements of an array of String with elements of an array of Int into a new array of String

If you don't want to use zip(_:_:), you can create your own Array extension method in order to have the expected result. The Playground code below shows how to create it:

extension Array where Element == String {    func mergeLettersWithNumbers(from numberArray: [Int]) -> [String] {        var index = startIndex        let iterator: AnyIterator<String> = AnyIterator {            defer { index = self.index(index, offsetBy: 1) }            guard index < self.endIndex, index < numberArray.endIndex else { return nil }            return self[index] + String(numberArray[index])        }        return Array(iterator)    }}let letterArray = ["a", "b", "c", "d", "e"]let numberArray = [1, 2, 3, 4, 5, 6, 7]let newArray = letterArray.mergeLettersWithNumbers(from: numberArray)print(newArray) // prints ["a1", "b2", "c3", "d4", "e5"]