Convert dictionary values to a different type in Swift

Viewed 6370

I have have a dictionary. I would like to go through it and convert the values to a different type. .map{ } would be perfect except this is a dictionary and not an array. So, I found a mapPairs function on stack overflow that should work for dictionaries. Unfortunately I get a conversion error.

extension Dictionary {
    //    Since Dictionary conforms to CollectionType, and its Element typealias is a (key, value) tuple, that means you ought to be able to do something like this:
    //
    //    result = dict.map { (key, value) in (key, value.uppercaseString) }
    //
    //    However, that won't actually assign to a Dictionary-typed variable. THE MAP METHOD IS DEFINED TO ALWAYS RETURN AN ARRAY (THE [T]), even for other types like dictionaries. If you write a constructor that'll turn an array of two-tuples into a Dictionary and all will be right with the world:
    //  Now you can do this:
    //    result = Dictionary(dict.map { (key, value) in (key, value.uppercaseString) })
    //
    init(_ pairs: [Element]) {
        self.init()
        for (k, v) in pairs {
            self[k] = v
        }
    }

    //    You may even want to write a Dictionary-specific version of map just to avoid explicitly calling the constructor. Here I've also included an implementation of filter:
    //    let testarr = ["foo" : 1, "bar" : 2]
    //    let result = testarr.mapPairs { (key, value) in (key, value * 2) }
    //    result["bar"]
    func mapPairs<OutKey: Hashable, OutValue>(@noescape transform: Element throws -> (OutKey, OutValue)) rethrows -> [OutKey: OutValue] {
        return Dictionary<OutKey, OutValue>(try map(transform))
    }

}

var dict1 = ["a" : 1, "b": 2, "c": 3]

let convertedDict: [String: String] = dict1.mapPairs { // ERROR: cannot convert value of type '_ -> (String, Int)' to expected argument type '(String, Int) -> (String, String)'
    element -> (String, Int) in
        element[0] = String(element.1)
        return element
}
4 Answers

In Swift 5 and later:

let originalDict: [TypeA: TypeB] = /* */
let convertedDict: [TypeA: TypeC] = originalDict.mapValues { /* conversion here */ }

Example:

let integerDict: [String: Int] = ["a": 1, "b": 2]
let doubleDict: [String: Double] = integerDict.mapValues(Double.init)

print(doubleDict) // ["a": 1.0, "b": 2.0]
Related