Swift 相当于 `[NSDictionary initWithObjects: forKeys:]`
Swift equivalent to `[NSDictionary initWithObjects: forKeys:]`
是否有 Swift 的原生 Dictionary
与 [NSDictionary initWithObjects: forKeys:]
的等价物?
假设我有两个包含键和值的数组,我想将它们放入字典中。在 Objective-C 我会这样做:
NSArray *keys = @[@"one", @"two", @"three"];
NSArray *values = @[@1, @2, @3];
NSDictionary *dict = [[NSDictionary alloc] initWithObjects: values forKeys: keys];
当然我可以用一个计数器遍历两个数组,使用 var dict: [String:Int]
并逐步添加内容。但这似乎不是一个好的解决方案。使用 zip
和 enumerate
可能是同时迭代两者的更好方法。然而,这种方法意味着有一个可变的字典,而不是一个不可变的字典。
let keys = ["one", "two", "three"]
let values = [1, 2, 3]
// ???
let dict: [String:Int] = ["one":1, "two":2, "three":3] // expected result
您可以简单地使用 Swift 相当于 initWithObjects:forKeys:
let keys = ["one", "two", "three"]
let values = [1, 2, 3]
var dict = NSDictionary.init(objects: values, forKeys: keys)
使用结构的纯 Swift 解决方案。使用 zip
将两个数组作为元组进行迭代,然后为元组中的每个键、值创建一个字典。
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))]"
您也可以在 zip
上使用 forEach
:
var dict = [String : Any]()
zip(keys, values).forEach { dict[[=11=].0] = [=11=].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"
A one-liner, 使用 zip
和 reduce
:
let dict = zip(keys, values).reduce([String:Int]()){ var d = [=10=]; d[.0] = .1; return d }
您可以通过为 Dictionary
和 tuple
定义 +
运算符来缩短 reduce
表达式:
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: +)
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]
如果与 zip 解决方案相比有什么区别?
很难说...对我来说 zip 类型注释是最大的问题
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]
但枚举解决方案也更快一些
从 Swift 4 开始,您可以直接从
key/value 对序列:
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]
这里假设所有的键都是不同的,否则会中止
出现运行时异常。
如果不能保证键是不同的,那么你可以这样做
let keys = ["one", "two", "one"]
let values = [1, 2, 3]
let dict = Dictionary(zip(keys, values), uniquingKeysWith: { })
print(dict) // ["one": 3, "two": 2]
第二个参数是一个闭包,它决定了哪个值"wins"
在重复键的情况下。
是否有 Swift 的原生 Dictionary
与 [NSDictionary initWithObjects: forKeys:]
的等价物?
假设我有两个包含键和值的数组,我想将它们放入字典中。在 Objective-C 我会这样做:
NSArray *keys = @[@"one", @"two", @"three"];
NSArray *values = @[@1, @2, @3];
NSDictionary *dict = [[NSDictionary alloc] initWithObjects: values forKeys: keys];
当然我可以用一个计数器遍历两个数组,使用 var dict: [String:Int]
并逐步添加内容。但这似乎不是一个好的解决方案。使用 zip
和 enumerate
可能是同时迭代两者的更好方法。然而,这种方法意味着有一个可变的字典,而不是一个不可变的字典。
let keys = ["one", "two", "three"]
let values = [1, 2, 3]
// ???
let dict: [String:Int] = ["one":1, "two":2, "three":3] // expected result
您可以简单地使用 Swift 相当于 initWithObjects:forKeys:
let keys = ["one", "two", "three"]
let values = [1, 2, 3]
var dict = NSDictionary.init(objects: values, forKeys: keys)
使用结构的纯 Swift 解决方案。使用 zip
将两个数组作为元组进行迭代,然后为元组中的每个键、值创建一个字典。
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))]"
您也可以在 zip
上使用 forEach
:
var dict = [String : Any]()
zip(keys, values).forEach { dict[[=11=].0] = [=11=].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"
A one-liner, 使用 zip
和 reduce
:
let dict = zip(keys, values).reduce([String:Int]()){ var d = [=10=]; d[.0] = .1; return d }
您可以通过为 Dictionary
和 tuple
定义 +
运算符来缩短 reduce
表达式:
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: +)
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]
如果与 zip 解决方案相比有什么区别? 很难说...对我来说 zip 类型注释是最大的问题
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]
但枚举解决方案也更快一些
从 Swift 4 开始,您可以直接从 key/value 对序列:
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]
这里假设所有的键都是不同的,否则会中止 出现运行时异常。
如果不能保证键是不同的,那么你可以这样做
let keys = ["one", "two", "one"]
let values = [1, 2, 3]
let dict = Dictionary(zip(keys, values), uniquingKeysWith: { })
print(dict) // ["one": 3, "two": 2]
第二个参数是一个闭包,它决定了哪个值"wins" 在重复键的情况下。