有没有什么方法可以创建一个带有Optional
键的字典?我知道这个问题的妥善解决需要实现条件遵从,但在那之前我有其他选择吗?
let dict: [Int?: Int] = [nil: 1]
// ERROR: type 'Int?' does not conform to protocol 'Hashable'
有没有什么方法可以创建一个带有Optional
键的字典?我知道这个问题的妥善解决需要实现条件遵从,但在那之前我有其他选择吗?
let dict: [Int?: Int] = [nil: 1]
// ERROR: type 'Int?' does not conform to protocol 'Hashable'
条件一致性已在Swift 4.2中实现,棒极了!
这允许当包装的元素是Hashable
时,可以有条件地使Optional
成为Hashable
。因此,您可以直接将任何Optional<T: Hashable>
用作字典键!
let d: [Int?: String] = [
nil: "nil",
1: "a",
2: "b",
3: "c",
]
for (key, value) in d {
let stringKey = key.map(String.init(describing:)) ?? "nil"
print("\(stringKey): \(value)")
}
这里有一个我找到的解决方法:创建一个新的HashableOptional
枚举
:
enum HashableOptional<Wrapped: Hashable> {
case none
case some(Wrapped)
public init(_ some: Wrapped) {
self = .some(some)
}
public init(_ optional: Wrapped?) {
self = optional.map{ .some($0) } ?? .none
}
public var value: Wrapped? {
switch self {
case .none: return nil
case .some(let wrapped): return wrapped
}
}
}
extension HashableOptional: Equatable {
static func ==(lhs: HashableOptional, rhs: HashableOptional) -> Bool {
switch (lhs, rhs) {
case (.none, .none): return true
case (.some(let a), .some(let b)): return a == b
default: return false
}
}
}
extension HashableOptional: Hashable {
var hashValue: Int {
switch self {
case .none: return 0
case .some(let wrapped): return wrapped.hashValue
}
}
}
extension HashableOptional: ExpressibleByNilLiteral {
public init(nilLiteral: ()) {
self = .none
}
}
然后你可以像这样使用它:
let dict: [HashableOptional<Int>: Int] = [nil: 1]
Wrapped?
base
属性的 "struct",然后仅在需要访问可选值时引用 key.base
。因为Optional
带有很多内置的语言特性,在包装器本身上无法复制(可选链式调用、可选绑定、隐式提升、语法糖模式等),所以在包装器和底层值之间做明确区分可以提供更一致的接口。 - Hamish
nil
键表示没有值,而且该类型无法转换为NSDictionary
,因为Foundation类型仅支持非可选类型作为键和值。 - vadianNSDictionary
用于鸟类。这是我的使用情况:我正在构建一个类层次结构,包括 Objective C 运行时中的各个类。这个字典将把类映射到它们的子类数组上。根类具有一个“nil”超类,通过class_getSuperclass
给出。 - AlexanderNSDictionary
进行桥接,因为nil
被桥接为NSNull
。 - Hamish