目前我正在开发一种数据结构,旨在唯一地存储存储键值对,并按键对它们进行排序。本质上它是一个排序的字典,因此我想尽可能多地保留Swift的Collection和Dictionary语义。
在文档和Swift源代码中(尽我所能),Dictionaries有两个下标。一个是最常用的subscript by key (Github source):
extension Dictionary {
...
public subscript(key: Key) -> Value? {
@inline(__always)
get {
return _variantBuffer.maybeGet(key)
}
set(newValue) {
if let x = newValue {
// FIXME(performance): this loads and discards the old value.
_variantBuffer.updateValue(x, forKey: key)
}
else {
// FIXME(performance): this loads and discards the old value.
removeValue(forKey: key)
}
}
}
...
}
第二个是subscript by position/index (Github) source),作为其与Collection协议一致性的一部分:
extension Dictionary: Collection {
...
public subscript(position: Index) -> Element {
return _variantBuffer.assertingGet(position)
}
...
}
当使用由Int
之外的其他内容键入的词典时,它们的行为完全符合预期,因为下标由不同的参数类型区分,即:String
vs Int
。
let stringKeys = ["One": 1, "Two": 2, "Three": 3]
stringKeys["One"] // 1
stringKeys[1] // ("Two", 2)
当Int
用作键时,键盘下标将根据需要使用。
let intKeys = [1: "One, 2: "Two, 3: "Three"]
intKeys[1] // "One"
Dictionary类型如何实现这一目标?在我看来,下标的Index
和Key
参数都是Int
,并且编译器不应该知道哪些是预期的。实际上,当我为自定义词典实现相同的下标时,编译器会给出错误 - “模糊地使用'下标'” - 当我使用Int
键进行测试时。
首先,我想知道一个是否是协议扩展中提供的默认值,并被更具体的实现覆盖,但从我上面所说的并非如此。我唯一的另一个理论是Index
是除了'Int`以外的其他类型,因此它仍然是明确的,但我找不到任何证实这一点的方法。任何人都可以对此有所了解吗?除了我的直接需求之外,我想了解Swift中的一个非常聪明的行为。
感谢大家的阅读和帮助!
答案 0 :(得分:1)
我唯一的另一个理论是,索引是“Int”以外的其他类型,因此它仍然是明确的,但我无法找到确认这一点的任何东西。
这就是它的确切方式。 Dictionary
有两个下标方法:
public subscript(key: Dictionary.Key) -> Dictionary.Value?
public subscript(position: Dictionary<Key, Value>.Index) -> Dictionary.Element { get }
第一个接受一个键并返回一个(可选)值,
第二个需要Dictionary.Index
(source code)
并返回(可选)Dictionary.Element
,
即一个键值对。
例如:
let d : Dictionary = [1 : "one"]
if let idx = d.index(forKey: 1) {
print(String(reflecting: type(of: idx))) // Swift.Dictionary<Swift.Int, Swift.String>.Index
let kv = d[idx]
print(String(reflecting: type(of: kv))) // (key: Swift.Int, value: Swift.String)
}
Dictionary.Index
也用于其他方法,例如
public var startIndex: Dictionary<Key, Value>.Index { get }
public var endIndex: Dictionary<Key, Value>.Index { get }
public func index(where predicate: ((key: Key, value: Value)) throws -> Bool) rethrows -> Dictionary<Key, Value>.Index?
是Collection
协议的一部分。
通常,Index
的关联Collection
类型不是
必须是Int
,另一个例子是String
拥有String.Index
类型。