Last active
November 1, 2019 05:08
-
-
Save ijoshsmith/0c966b1752b9a5722e23 to your computer and use it in GitHub Desktop.
Create Swift Dictionary from Array
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
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] |
@InsertNetan awesome, thx, I was looking for exactly this thing! ;)
@Buju77 thanks, i'm really glad to hear
How about this update to make it compatible with Swift 2.2?
extension CollectionType {
func toDictionary<K, V>
(transform:(element: Self.Generator.Element) -> (key: K, value: V)?) -> [K : V] {
var dictionary = [K : V]()
for e in self {
if let (key, value) = transform(element: e) {
dictionary[key] = value
}
}
return dictionary
}
}
@KevM nice, thx for the update for Swift 2.2! 👍
How about this version? Slightly improved snippet from @KevM
extension CollectionType {
func toDictionary<K, V>(transform:(element: Self.Generator.Element) -> [K: V]) -> [K: V] {
var dictionary = [K: V]()
self.forEach { e in
let dict = transform(element: e)
for (key, value) in dict {
dictionary[key] = value
}
}
return dictionary
}
}
Anything about Swift 3 ?
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] }
What about making this without that var
?
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
in the spirit of swift 2:
from a global function to CollectionType extension
this way with a given transform function we can map any collectionType into a dictionary.