Dan Beaulieu
Dan Beaulieu

Reputation: 19954

How do you use the map function in Swift?

I'm trying to understand how .map works and all of my searches are returning examples that aren't helping me resolve my issue. From my understanding .map is a cleaner way of performing a for-in loop, the only difference is that .map replaces your original creates a new array and for-in just alters your original arrays values.

Attempt

In the code example below, I'm expecting the .map function to replace my wheels array with new Tire objects whose state properties are all set to .Flat.

This is a playground-ready version of what I'm trying to accomplish in my program:

enum State {
    case Ok, Flat
}

class Tire {

    var state = State.Ok

    init(t: State) {
        state = t
    }
}

var wheels = [Tire(t: .Ok), Tire(t: .Ok), Tire(t: .Ok)]

wheels = wheels.map { $0.state = .Flat }

Result

error: cannot convert value of type '()' to closure result type 'Tire' wheels = wheels.map { $0.state = .Flat } ~~~~~~~~~^~~~~~~

Question

In the given situation, how can I set all of my Tire objects states to .Flat using .map?

Upvotes: 7

Views: 15082

Answers (2)

David Berry
David Berry

Reputation: 41226

There are 2 similar key functions which perform similar operations, the basic purpose of which is to take an array and build another array from it:

func map(transform:(R)->T) -> [T] --- Map takes an array of elements of one type and converts it to an array of elements of (potentially) another type, by calling a transform function on each element in turn. So you can convert an array of Int's to an array of strings:

[1, 2, 3, 4].map { "\($0)" } // --> ["1", "2", "3", "4"]

func filter(predicate:(T)->Boolean) -> [T] -- Filter takes an array of elements and converts it to an array of elements of the same type, but only includes those elements for which predicate returns true. So you can filter an array of ints to leave only the even numbers:

[1, 2, 3, 4].filter { $0 % 2 == 0 } // --> [ 2, 4]

There are other variants, such as flatMap which takes [[T]] and turns it into [T] by iterating over the input and array and appending the contents of each array to an output array:

[ [1, 2], [3, 4]].flatMap() // --> [1, 2, 3, 4]

It's also worth nothing that the concept behind map is that, in simplistic terms, it can be used to map any input type to an output type, so you can define:

func <R, T> map(in:R?, transform:(R)->T) -> T?

for example, which would translate any optional input type into an optional output type given a function that translates the base type.

Upvotes: 6

Code Different
Code Different

Reputation: 93171

The problem is $0.state = .Flat is an assignment. It does not return a value. Try this:

wheels = wheels.map { w in
    w.state = .Flat
    return w
}

map does not replace anything. It projects each element from your array to a new array by applying the transformation block. You can choose to assign this new array to the old array, but otherwise it will not alter the original array.

Upvotes: 5

Related Questions