Is there an equivalent for Swift's native Dictionary
to [NSDictionary initWithObjects: forKeys:]
?
Say I have two arrays with keys and values and want to put them in a dictionary. In Objective-C I'd do it like this:
NSArray *keys = @[@"one", @"two", @"three"];
NSArray *values = @[@1, @2, @3];
NSDictionary *dict = [[NSDictionary alloc] initWithObjects: values forKeys: keys];
Of course I can iterate with a counter through both arrays, use a var dict: [String:Int]
and add stuff step by step. But that doesn't seem to be a good solution. Using zip
and enumerate
are probably better ways of iterating over both at the same time. However this approach means having a mutable dictionary, not an immutable one.
let keys = ["one", "two", "three"]
let values = [1, 2, 3]
// ???
let dict: [String:Int] = ["one":1, "two":2, "three":3] // expected result
As of Swift 4 you can create a dictionary directly from a sequence of key/value pairs:
let keys = ["one", "two", "three"]
let values = [1, 2, 3]
let dict = Dictionary(uniqueKeysWithValues: zip(keys, values))
print(dict) // ["one": 1, "three": 3, "two": 2]
This assumes that all keys are different, otherwise it will abort with a runtime exception.
If the keys are not guaranteed to be distinct then you can do
let keys = ["one", "two", "one"]
let values = [1, 2, 3]
let dict = Dictionary(zip(keys, values), uniquingKeysWith: { $1 })
print(dict) // ["one": 3, "two": 2]
The second argument is a closure which determines which value "wins" in the case of duplicate keys.
You can simply use the Swift equivalent of initWithObjects:forKeys:
let keys = ["one", "two", "three"]
let values = [1, 2, 3]
var dict = NSDictionary.init(objects: values, forKeys: keys)
Working pure Swift solution with structs. Use zip
to iterate through your two arrays as a tuple, and then create a dictionary for each key, value in the tuple.
struct SomeStruct {
var someVal: Int?
}
var keys = [String]()
var values = [SomeStruct]()
for index in 0...5 {
keys.append(String(index))
values.append(SomeStruct(someVal: index))
}
var dict = [String : Any]()
for (key, value) in zip(keys, values) {
dict[key] = value
}
print(dict) // "["4": SomeStruct(someVal: Optional(4)), "2": SomeStruct(someVal: Optional(2)), "1": SomeStruct(someVal: Optional(1)), "5": SomeStruct(someVal: Optional(5)), "0": SomeStruct(someVal: Optional(0)), "3": SomeStruct(someVal: Optional(3))]"
You could also use forEach
on zip
:
var dict = [String : Any]()
zip(keys, values).forEach { dict[$0.0] = $0.1 }
print(dict) // "["4": SomeStruct(someVal: Optional(4)), "2": SomeStruct(someVal: Optional(2)), "1": SomeStruct(someVal: Optional(1)), "5": SomeStruct(someVal: Optional(5)), "0": SomeStruct(someVal: Optional(0)), "3": SomeStruct(someVal: Optional(3))]\n"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With