使用
通过传入一个不重复的 key 的元组,可以转为字典
1 2 3
| let pairs = [("1", 1), ("2", 2), ("3", 3), ("1", 2)] Dictionary(uniqueKeysWithValues: pairs)
|
如果存在重复的 key,则会直接抛出异常 **Fatal error: Duplicate values for key:**
1 2 3 4 5
| let pairs = [("1", 1), ("2", 2), ("3", 3), ("1", 4)] let dict = Dictionary(pairs, uniquingKeysWith: { first, _ in first })
let dict = Dictionary(pairs, uniquingKeysWith: { _, last in last })
|
这一方法则可以处理存在相同 key 的情况,并且通过 uniquingKeysWith,确定 key 使用前面还是后面的值
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @inlinable public init<S: Sequence>( uniqueKeysWithValues keysAndValues: S ) where S.Element == (Key, Value) { if let d = keysAndValues as? Dictionary<Key, Value> { self = d } else { self = Dictionary(minimumCapacity: keysAndValues.underestimatedCount) try! _variantBuffer.merge( keysAndValues, uniquingKeysWith: { _, _ in throw _MergeError.keyCollision}) } }
|
我们主要看 else 内容,可以看到,实际调用的 Dictionary(keysAndValues: Sequence, uniquingKeysWith: (_, _) throws -> _) 这一方法,并且 uniquingKeysWith 传入的是一个异常,如果执行就会挂掉
我们再来看之后的方法,里面并没有什么内容,大多数是申请内存相关的,最后是调用了 nativeMerge 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @inlinable public init<S: Sequence>( _ keysAndValues: S, uniquingKeysWith combine: (Value, Value) throws -> Value ) rethrows where S.Element == (Key, Value) { self = Dictionary(minimumCapacity: keysAndValues.underestimatedCount) try _variantBuffer.merge(keysAndValues, uniquingKeysWith: combine) }
@inlinable internal mutating func merge<S: Sequence>( _ keysAndValues: S, uniquingKeysWith combine: (Value, Value) throws -> Value ) rethrows where S.Element == (Key, Value) { ensureNativeBuffer() try nativeMerge(keysAndValues, uniquingKeysWith: combine) }
|
主要的内容就在这一方法中,其中涉及较多底层内存空间申请等相关逻辑,推荐 Swift标准库源码阅读笔记 - Dictionary 这篇文章了解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| @inlinable internal mutating func nativeMerge<S: Sequence>( _ keysAndValues: S, uniquingKeysWith combine: (Value, Value) throws -> Value ) rethrows where S.Element == (Key, Value) { for (key, value) in keysAndValues { var (i, found) = asNative._find(key, startBucket: asNative._bucket(key)) if found { let bucketCount = asNative.bucketCount _ = ensureUniqueNativeBuffer(withBucketCount: bucketCount) do { let newValue = try combine(asNative.value(at: i.offset), value) asNative.setKey(key, value: newValue, at: i.offset) } catch _MergeError.keyCollision { fatalError("Duplicate values for key: '\(key)'") } } else { let minCapacity = asNative.count + 1 let (_, capacityChanged) = ensureUniqueNativeBuffer( withCapacity: minCapacity) if capacityChanged { i = asNative._find(key, startBucket: asNative._bucket(key)).pos }
asNative.initializeKey(key, value: value, at: i.offset) asNative.count += 1 } } }
|
可以看到,通过传入的 combine,可以对 value 做多种处理,比如相加等等,对一个 Array,zip 后传入,可以做到计算 key 的次数
链接
Swift - Dictionary
Swift标准库源码阅读笔记 - Dictionary