swiftmapsreduce

Iterating array of array in swift using map


I am trying to udnerstand the concept of map function in swift. I want to iterate an array of array in such a way that I can print each element in every array along with it's index. Below is my code

var raceResults = [["one","two","four"],["two","one","five","six"],["two","one","four","ten"],["one","two","four"]]

   raceResults.map {
        return $0 // Returns first array 
    }.map { 
        print($0) // was expecting each element in first array here but it's whole array 
    }

I am wondering how can I get hold over every single element in array using chaining ?


Solution

  • Let's start with a single array, like:

    let raceResult = ["one", "two", "four"]
    

    If we want to combine each element with an offset counting from 0, we can use Array.enumerated(), along with map.

    let numberedRaceResult = raceResult
        .enumerated()
        .map { offset, element in "\(offset). \(element)" }
    
    for numberedResult in numberedRaceResult {
        print(numberedResult)
    }
    
    // Prints:
    // 0. one
    // 1. two
    // 2. four
    

    You can see that I didn't call print inside the closure passed to map. You can do this, but it kind of defeats the purpose of map (which is to create an equal-sized output array from the transformed elements of the input array), because the result would be unused. In that case, it makes more sense to just use a for loop or a call to forEach, like @Sh_Khan showed.

    To handle a nested array, it's much the same. We can use the same logic as for one array, but apply it to each sub-array.

    let raceResults = [
        ["one", "two", "four"],
        ["two", "one", "five", "six"],
        ["two", "one", "four", "ten"],
        ["one", "two", "four"],
    ]
    
    let numberedRaceResults = raceResults
        .enumerated()
        .flatMap { outterOffset, raceResult in
            raceResult
                .enumerated()
                .map { innerOffset, element in "\(outterOffset).\(innerOffset). \(element)" }
        }
    
    for numberedResult in numberedRaceResults {
        print(numberedResult)
    }
    
    // Prints:
    // 0.0. one
    // 0.1. two
    // 0.2. four
    // 1.0. two
    // 1.1. one
    // 1.2. five
    // 1.3. six
    // 2.0. two
    // 2.1. one
    // 2.2. four
    // 2.3. ten
    // 3.0. one
    // 3.1. two
    // 3.2. four
    

    You'll notice that I used flatMap on the outter array, instead of a simple map. You can change it back and forth and compare the result. In short, flatMap gives you a single flat array of string results, rather than an array of sub-arrays of strings.