Swift中不区分大小写的字典
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Swift中不区分大小写的字典相关的知识,希望对你有一定的参考价值。
鉴于Dictionary
的Key
类型为String
,有没有办法以不区分大小写的方式访问该值?例如:
let dict = [
"name": "John",
"location": "Chicago"
]
有没有办法打电话给qazxsw poi等,仍然可以获得qazxsw poi?
Swift支持多个下标,因此您可以利用它来定义不区分大小写的访问者:
dict["NAME"], dict["nAmE"]
此扩展仅限于"John"
,其extension Dictionary where Key : StringLiteralConvertible {
subscript(ci key : Key) -> Value? {
get {
let searchKey = String(key).lowercaseString
for k in self.keys {
let lowerK = String(k).lowercaseString
if searchKey == lowerK {
return self[k]
}
}
return nil
}
}
}
// Usage:
let dict = [
"name": "John",
"location": "Chicago",
]
print(dict[ci: "NAME"]) // John
print(dict[ci: "lOcAtIoN"]) // Chicago
的类型为Dictionary
(因为小写与其他数据类型无关)。但是,Swift会抱怨将一般类型限制为Key
。最接近String
的协议是struct
。
请注意,如果您有两个小写形式相同的键,则无法保证您将获得哪一个:
String
更清洁的方法,迅捷4:
StringLiteralConvertible
现有的答案很好,但是那些策略的查找/插入的时间复杂度从O(1)到O(N)(其中N是字典中的对象数)恶化。
要保留O(1),您可能需要考虑以下方法:
let dict = [
"name": "John",
"NAME": "David",
]
print(dict[ci: "name"]) // no guarantee that you will get David or John.
可以使用extension Dictionary where Key == String {
subscript(caseInsensitive key: Key) -> Value? {
get {
if let k = keys.first(where: { $0.caseInsensitiveCompare(key) == .orderedSame }) {
return self[k]
}
return nil
}
set {
if let k = keys.first(where: { $0.caseInsensitiveCompare(key) == .orderedSame }) {
self[k] = newValue
} else {
self[key] = newValue
}
}
}
}
// Usage:
var dict = ["name": "John"]
dict[caseInsensitive: "NAME"] = "David" // overwrites "name" value
print(dict[caseInsensitive: "name"]!) // outputs "David"
从映射为小写的所有键中找到第一个小写匹配,然后从此结果返回值。
/// Wrapper around String which uses case-insensitive implementations for Hashable
public struct CaseInsensitiveString: Hashable, LosslessStringConvertible, ExpressibleByStringLiteral {
public typealias StringLiteralType = String
private let value: String
private let caseInsensitiveValue: String
public init(stringLiteral: String) {
self.value = stringLiteral
self.caseInsensitiveValue = stringLiteral.lowercased()
}
public init?(_ description: String) {
self.init(stringLiteral: description)
}
public var hashValue: Int {
return self.caseInsensitiveValue.hashValue
}
public static func == (lhs: CaseInsensitiveString, rhs: CaseInsensitiveString) -> Bool {
return lhs.caseInsensitiveValue == rhs.caseInsensitiveValue
}
public var description: String {
return value
}
}
var dict = [CaseInsensitiveString: String]()
dict["name"] = "John"
dict["NAME"] = "David" // overwrites "name" value
print(dict["name"]!) // outputs "David"
Collection's first(where:)
是一种过滤或迭代大型集合的高效方法
参考:
extension Dictionary where Key == String { func valueForKeyInsensitive<T>(key: Key) -> T? { let foundKey = self.keys.first { $0.compare(key, options: .caseInsensitive) == .orderedSame } ?? key return self[foundKey] as? T } }
first(where:)
以上是关于Swift中不区分大小写的字典的主要内容,如果未能解决你的问题,请参考以下文章