Skip to content

Instantly share code, notes, and snippets.

@ijoshsmith
Last active November 1, 2019 05:08
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ijoshsmith/0c966b1752b9a5722e23 to your computer and use it in GitHub Desktop.
Save ijoshsmith/0c966b1752b9a5722e23 to your computer and use it in GitHub Desktop.
Create Swift Dictionary from Array
/**
Creates a dictionary with an optional
entry for every element in an array.
*/
func toDictionary<E, K, V>(
array: [E],
transformer: (element: E) -> (key: K, value: V)?)
-> Dictionary<K, V>
{
return array.reduce([:]) {
(var dict, e) in
if let (key, value) = transformer(element: e)
{
dict[key] = value
}
return dict
}
}
struct Person
{
let name: String
let age: Int
}
let people = [
Person(name: "Billy", age: 42),
Person(name: "David", age: 24),
Person(name: "Maria", age: 99)]
let dictionary = toDictionary(people) { ($0.name, $0.age) }
println(dictionary)
// Prints: [Billy: 42, David: 24, Maria: 99]
@TheNamesJamesW
Copy link

TheNamesJamesW commented Nov 12, 2016

In case people are looking for a Swift 3 version

extension Collection {
    func dictionary<K, V>(transform:(_ element: Iterator.Element) -> [K : V]) -> [K : V] {
        var dictionary = [K : V]()
        self.forEach { element in
            for (key, value) in transform(element) {
                dictionary[key] = value
            }
        }
        return dictionary
    }
}

And you'd use it something like this

let dictionary = people.dictionary { [$0.name : $0.age] }

Or, for those who might prefer an initialiser pattern:

extension Dictionary {
    init<C: Collection>(_ collection: C, transform:(_ element: C.Iterator.Element) -> [Key : Value]) {
        self.init()
        collection.forEach { (element) in
            for (k, v) in transform(element) {
                self[k] = v
            }
        }
    }
}

Which rounds out to

let dictionary = Dictionary(people) { [$0.name : $0.age] }

@eonist
Copy link

eonist commented Apr 25, 2017

What about making this without that var ?

@stefc
Copy link

stefc commented Dec 17, 2017

This is my suggestion of the extension using the reduce(into:) method of the swift standard library

extension Collection {
    func dictionary<K:Hashable, V>(transform:(_ element: Iterator.Element) -> (key:K, value:V)) -> [K : V] {
        return self.reduce(into: [K : V]()) { (accu, current) in
            let kvp = transform(current)
            accu[kvp.key] = kvp.value
        }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment