Расширьте словарь, где Key имеет тип String
Я хочу расширить метод словаря, но только если ключ имеет тип String.
Я пытаюсь сделать это:
extension Dictionary where Key: String {
mutating func lowercaseKeys() {
for key in self.keys {
self[key.lowercase] = self.removeValueForKey(key)
}
}
}
И получите ошибку:
Введите "Ключ", ограниченный не-протокольным типом "String"
Основываясь на этом сообщении об ошибке, я могу сказать, что я могу делать такую фильтрацию только с протоколами... Есть ли способ обходить это?
Ответы
Ответ 1
Я считаю, что ближайший протокол, отвечающий вашим потребностям, StringLiteralConvertible
, который с несколькими дополнительными строками позволит вам выполнить этот
extension Dictionary where Key: StringLiteralConvertible {
mutating func setAllKeysLowercase() {
for key in self.keys {
if let lowercaseKey = String(key).lowercaseString as? Key {
self[lowercaseKey] = self.removeValueForKey(key)
}
}
}
}
var stringKeyDictionary = [ "Hello" : NSObject(), "World" : NSObject() ]
stringKeyDictionary.setAllKeysLowercase()
print( stringKeyDictionary )
// Prints: ["hello": <NSObject: 0x1007033c0>, "world": <NSObject: 0x1007033d0>]
var numberKeyDictionary = [ 0 : NSObject(), 1: NSObject() ]
numberKeyDictionary.setAllKeysLowercase() //< Won't compile, keys are not strings
Ответ 2
Я обновил это для Swift 4.
extension Dictionary where Key: StringProtocol {
mutating func setAllKeysLowercase() {
for key in self.keys {
if let lowercaseKey = key.lowercased() as? Key {
self[lowercaseKey] = self.removeValue(forKey: key)
}
}
}
}
var stringKeyDictionary = [ "Hello" : 123, "World" : 456 ]
stringKeyDictionary.setAllKeysLowercase()
print( stringKeyDictionary )
Отпечатки: ["hello": 123, "world": 456]
var numberKeyDictionary = [ 0 : 123, 1: 456 ]
numberKeyDictionary.setAllKeysLowercase()
дает ошибку: error: cannot use mutating member on immutable value: 'numberKeyDictionary' is immutable
Так как StringLiteralConvertible
устарел, я подумал, что лучше использовать StringProtocol
вместо эквивалента Swift4 ExpressibleByStringLiteral
. Использование ExpressibleByStringLiteral
означает, что ключ не является строкой, поэтому не может использовать методы String, такие как lowercased
.