Map array of objects to Dictionary in Swift Map array of objects to Dictionary in Swift ios ios

Map array of objects to Dictionary in Swift


Since Swift 4 you can do @Tj3n's approach more cleanly and efficiently using the into version of reduce It gets rid of the temporary dictionary and the return value so it is faster and easier to read.

Sample code setup:

struct Person {     let name: String    let position: Int}let myArray = [Person(name:"h", position: 0), Person(name:"b", position:4), Person(name:"c", position:2)]

Into parameter is passed empty dictionary of result type:

let myDict = myArray.reduce(into: [Int: String]()) {    $0[$1.position] = $1.name}

Directly returns a dictionary of the type passed in into:

print(myDict) // [2: "c", 0: "h", 4: "b"]


Okay map is not a good example of this, because its just same as looping, you can use reduce instead, it took each of your object to combine and turn into single value:

let myDictionary = myArray.reduce([Int: String]()) { (dict, person) -> [Int: String] in    var dict = dict    dict[person.position] = person.name    return dict}//[2: "b", 3: "c", 1: "a"]

In Swift 4 or higher please use the below answer for clearer syntax.


Since Swift 4 you can do this very easily. There are two new initializers that build a dictionary from a sequence of tuples (pairs of key and value). If the keys are guaranteed to be unique, you can do the following:

let persons = [Person(name: "Franz", position: 1),               Person(name: "Heinz", position: 2),               Person(name: "Hans", position: 3)]Dictionary(uniqueKeysWithValues: persons.map { ($0.position, $0.name) })

=> [1: "Franz", 2: "Heinz", 3: "Hans"]

This will fail with a runtime error if any key is duplicated. In that case you can use this version:

let persons = [Person(name: "Franz", position: 1),               Person(name: "Heinz", position: 2),               Person(name: "Hans", position: 1)]Dictionary(persons.map { ($0.position, $0.name) }) { _, last in last }

=> [1: "Hans", 2: "Heinz"]

This behaves as your for loop. If you don't want to "overwrite" values and stick to the first mapping, you can use this:

Dictionary(persons.map { ($0.position, $0.name) }) { first, _ in first }

=> [1: "Franz", 2: "Heinz"]

Swift 4.2 adds a third initializer that groups sequence elements into a dictionary. Dictionary keys are derived by a closure. Elements with the same key are put into an array in the same order as in the sequence. This allows you to achieve similar results as above. For example:

Dictionary(grouping: persons, by: { $0.position }).mapValues { $0.last! }

=> [1: Person(name: "Hans", position: 1), 2: Person(name: "Heinz", position: 2)]

Dictionary(grouping: persons, by: { $0.position }).mapValues { $0.first! }

=> [1: Person(name: "Franz", position: 1), 2: Person(name: "Heinz", position: 2)]