简体   繁体   中英

Lowercase Dictionary Keys in Swift

I need to convert a Dictionary with mixed case keys in the same exact Dictionary but with only lowercase keys.

Here is my attempt (It works but I found this implementation extremely rough)

extension Dictionary {
    func lowercaseKeys()->Dictionary<String, AnyObject>{
        var newDictionary = Dictionary<String,AnyObject>()

        for k in keys{
            if let k_string = k as? String{
                newDictionary[k_string.lowercaseString] = self[k] as? AnyObject
            }
        }
        return newDictionary
    }
}

Can you suggest a more elegant way to solve this problem?

Changes its own keys without the need of a temporary dictionary ;)

var dict = ["HEJ":"DÅ", "NeJ":"tack"]

for key in dict.keys {
    dict[key.lowercaseString] = dict.removeValueForKey(key)
}

print(dict)

[hej: DÅ, nej: tack]

EDIT

I made this extension, its a little dirty for now but I will update it again.

extension Dictionary {
    mutating func lowercaseKeys() {
        for key in self.keys {
            let str = (key as! String).lowercaseString
            self[str as! Key] = self.removeValueForKey(key)
        }
    }
}

var dict = ["HeJ":"Då", "nEJ":"taCK!"]
dict.lowercaseKeys()
print(dict)

["hej": "Då", "nej": "taCK!"]

EDIT 2

extension Dictionary where Key: StringLiteralConvertible {
    mutating func lowercaseKeys() {
        for key in self.keys {
            self[String(key).lowercaseString as! Key] = self.removeValueForKey(key)
        }
    }
}

var dict = ["NamE":"David", "LAST_NAME":"Göransson"]

dict.lowercaseKeys() // Will compile

var dict2 = [0:"David", 0:"Göransson"]

dict2.lowercaseKeys() // Won't compile because Key isn't StringLiteralConvertible

Smth like that?

  var dict = ["KEY": "value"]
  var newDict = [String: AnyObject]()

  for (key, value) in dict {
     newDict[key.lowercaseString] = value
  }

Arbitur's answer, updated for Swift 3:

extension Dictionary where Key: ExpressibleByStringLiteral {
    public mutating func lowercaseKeys() {
        for key in self.keys {
            self[String(describing: key).lowercased() as! Key] = self.removeValue(forKey: key)
        }
    }
}

Here is my solution, no force casting, totally safe.

protocol LowercaseConvertible {
    var lowercaseString: Self { get }
}

extension String: LowercaseConvertible {}

extension Dictionary where Key: LowercaseConvertible {
    func lowercaseKeys() -> Dictionary {
        var newDictionary = Dictionary()

        for k in keys {
            newDictionary[k.lowercaseString] = self[k]
        }
        return newDictionary
    }
}

Just as an alternative to looping, you could use the map function:

func lowercaseKeys () -> Dictionary<String, AnyObject> {
    var newDictionary = Dictionary<String,AnyObject>()
    Array(keys).map { key in
        newDictionary[(key as! String).lowercaseString] = self[key] as? AnyObject
    }
    return newDictionary
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM