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"]
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"]