给定一个Dictionary它Key的类型是String,有没有在不区分大小写的方式来访问值的方法吗?例如:
let dict = [
    "name": "John",
    "location": "Chicago"
]
有没有办法打电话dict["NAME"], dict["nAmE"]等等"John"?
更清洁的方法,快速4:
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"
Swift支持多个下标,因此您可以利用它来定义不区分大小写的访问者:
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于其Key类型String(因为小写对其他数据类型毫无意义).但是,Swift会抱怨将泛型类型约束为a struct.最接近的协议String是StringLiteralConvertible.
请注意,如果您有两个小写形式相同的键,则无法保证您将获得哪一个:
let dict = [
    "name": "John",
    "NAME": "David",
]
print(dict[ci: "name"])   // no guarantee that you will get David or John.
现有的答案很好,但是使用这些策略查找/插入的时间复杂度从 O(1) 恶化到 O(N)(其中 N 是字典中的对象数)。
要保留 O(1),您可能需要考虑以下方法:
/// 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"
| 归档时间: | 
 | 
| 查看次数: | 2901 次 | 
| 最近记录: |