Swift is equivalent to `[NSDictionary initWithObjects: forKeys:]`

Is there an equivalent for Swift native Dictionary to [NSDictionary initWithObjects: forKeys:] ?

Let's say I have two arrays with keys and values ​​and you want to put them in a dictionary. In Objective-C, I would 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 over the counter through both arrays, use var dict: [String:Int] and add the material step by step. But this does not seem to be a good solution. Using zip and enumerate is probably the best way to repeat 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 
+5
source share
5 answers

Single line using zip and reduce :

 let dict = zip(keys, values).reduce([String:Int]()){ var d = $0; d[$1.0] = $1.1; return d } 

You can shorten the reduce expression by specifying the + operator for Dictionary and tuple :

 func +<K,V>(lhs: [K:V], rhs: (K, V)) -> [K:V] { var result = lhs result[rhs.0] = rhs.1 return result } let dict = zip(keys, values).reduce([String:Int](), combine: +) 
+3
source

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) 
+5
source

Work with a clean Swift solution with structures. Use zip to iterate your two arrays as a tuple, and then create a dictionary for each key, the 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 can 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" 
+3
source
 let keys = ["one", "two", "three"] let values = [1, 2, 3] func createDict<K:Hashable,V>(keys: [K], values:[V])->[K:V] { var dict: [K:V] = [:] // add validity checks here by yourself ! // and return early, or throw an error ... keys.enumerate().forEach { (index,element) -> () in dict[element] = values[index] } return dict } let dict = createDict(keys, values: values) // ["one": 1, "three": 3, "two": 2] let dict2:[Int:Any] = createDict([1,2,3,4,5], values: [true,"two",3.4,5,[1,2,3]]) // [5: [1, 2, 3], 2: "two", 3: 3.4, 1: true, 4: 5] 

What is the difference when comparing it with a zip solution? hard to say ... for me, zip annotation is the biggest problem

 let a:Zip2Sequence<[Int],[Any]> = zip([1,2,3,4,5], [true,"two",3.4,5,[1,2,3]]) var d:[Int:Any] = [:] a.forEach { (key, value) -> () in d[key] = value } print(d) // [5: [1, 2, 3], 2: "two", 3: 3.4, 1: true, 4: 5] 

but listing the solution is also a little faster

+1
source

As in 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 they will be interrupted with an exception from the runtime.

If the keys are not guaranteed, 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.

+1
source

Source: https://habr.com/ru/post/1241140/


All Articles