Swift 4+

Good news! Swift 4 includes a mapValues(_:) method which constructs a copy of a dictionary with the same keys, but different values. It also includes a filter(_:) overload which returns a Dictionary, and init(uniqueKeysWithValues:) and init(_:uniquingKeysWith:) initializers to create a Dictionary from an arbitrary sequence of tuples. That means that, if you want to change both the keys and values, you can say something like:

let newDict = Dictionary(uniqueKeysWithValues:
    oldDict.map { key, value in (key.uppercased(), value.lowercased()) })

There are also new APIs for merging dictionaries together, substituting a default value for missing elements, grouping values (converting a collection into a dictionary of arrays, keyed by the result of mapping the collection over some function), and more.

During discussion of the proposal, SE-0165, that introduced these features, I brought up this Stack Overflow answer several times, and I think the sheer number of upvotes helped demonstrate the demand. So thanks for your help making Swift better!

Answer from Becca Royal-Gordon on Stack Overflow
Top answer
1 of 14
381

Swift 4+

Good news! Swift 4 includes a mapValues(_:) method which constructs a copy of a dictionary with the same keys, but different values. It also includes a filter(_:) overload which returns a Dictionary, and init(uniqueKeysWithValues:) and init(_:uniquingKeysWith:) initializers to create a Dictionary from an arbitrary sequence of tuples. That means that, if you want to change both the keys and values, you can say something like:

let newDict = Dictionary(uniqueKeysWithValues:
    oldDict.map { key, value in (key.uppercased(), value.lowercased()) })

There are also new APIs for merging dictionaries together, substituting a default value for missing elements, grouping values (converting a collection into a dictionary of arrays, keyed by the result of mapping the collection over some function), and more.

During discussion of the proposal, SE-0165, that introduced these features, I brought up this Stack Overflow answer several times, and I think the sheer number of upvotes helped demonstrate the demand. So thanks for your help making Swift better!

2 of 14
141

With Swift 5, you can use one of the five following snippets in order to solve your problem.


#1. Using Dictionary mapValues(_:) method

let dictionary = ["foo": 1, "bar": 2, "baz": 5]

let newDictionary = dictionary.mapValues { value in
    return value + 1
}
//let newDictionary = dictionary.mapValues { $0 + 1 } // also works

print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]

#2. Using Dictionary map method and init(uniqueKeysWithValues:) initializer

let dictionary = ["foo": 1, "bar": 2, "baz": 5]

let tupleArray = dictionary.map { (key: String, value: Int) in
    return (key, value + 1)
}
//let tupleArray = dictionary.map { (1 + 1) } // also works

let newDictionary = Dictionary(uniqueKeysWithValues: tupleArray)

print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]

#3. Using Dictionary reduce(_:_:) method or reduce(into:_:) method

let dictionary = ["foo": 1, "bar": 2, "baz": 5]

let newDictionary = dictionary.reduce([:]) { (partialResult: [String: Int], tuple: (key: String, value: Int)) in
    var result = partialResult
    result[tuple.key] = tuple.value + 1
    return result
}

print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]
let dictionary = ["foo": 1, "bar": 2, "baz": 5]

let newDictionary = dictionary.reduce(into: [:]) { (result: inout [String: Int], tuple: (key: String, value: Int)) in
    result[tuple.key] = tuple.value + 1
}

print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]

#4. Using Dictionary subscript(_:default:) subscript

let dictionary = ["foo": 1, "bar": 2, "baz": 5]

var newDictionary = [String: Int]()
for (key, value) in dictionary {
    newDictionary[key, default: value] += 1
}

print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]

#5. Using Dictionary subscript(_:) subscript

let dictionary = ["foo": 1, "bar": 2, "baz": 5]

var newDictionary = [String: Int]()
for (key, value) in dictionary {
    newDictionary[key] = value + 1
}

print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]
🌐
Sarunw
sarunw.com › posts › different-ways-to-map-dictionary-in-swift
Different ways to map over Dictionary in Swift | Sarunw
September 11, 2023 - If you want to transform the value part of a dictionary and keep the same key, you can use mapValues(_:). The syntax is similar to mapping over an array.
People also ask

How to map dictionary to model in Swift?
You can map a dictionary to a model in Swift by looping over the dictionary and assigning each key-value pair to a property in the model.
🌐
dhiwise.com
dhiwise.com › post › exploring-the-intricacies-of-swift-map-dictionary
The Ultimate Swift Map Dictionary Tutorial for Beginners
How to define a map in Swift?
In Swift, you can create a map (also known as a dictionary) by using the following syntax: ```swift var map = [KeyType: ValueType] ``` Where KeyType is the type of value that can be used as a dictionary key, and ValueType is the type of values that the dictionary holds.
🌐
dhiwise.com
dhiwise.com › post › exploring-the-intricacies-of-swift-map-dictionary
The Ultimate Swift Map Dictionary Tutorial for Beginners
What is mapValues in Swift dictionary?
The mapValues function in Swift is used to transform the values in a dictionary. Unlike the map function, mapValues returns a new dictionary with transformed values, and the original keys unchanged.
🌐
dhiwise.com
dhiwise.com › post › exploring-the-intricacies-of-swift-map-dictionary
The Ultimate Swift Map Dictionary Tutorial for Beginners
🌐
Apple Developer
developer.apple.com › documentation › swift › dictionary › mapvalues(_:)
mapValues(_:) | Apple Developer Documentation
Returns a new dictionary containing the keys of this dictionary with the values transformed by the given closure.
🌐
Swift Forums
forums.swift.org › using swift
Mapping a Dictionary to a Dictionary? - Using Swift - Swift Forums
August 29, 2016 - I may be missing something obvious, but I can’t find a library function that maps a Dictionary to another Dictionary, transforming the keys and/or values. The only method I’ve found is the regular map(), which results in…
🌐
DhiWise
dhiwise.com › post › exploring-the-intricacies-of-swift-map-dictionary
The Ultimate Swift Map Dictionary Tutorial for Beginners
July 10, 2024 - The map function applies a given transformation to each element of an array, creating a new array with the transformed elements. However, this function is not limited to arrays; it can also be used with dictionaries such as Swift dictionary maps.
🌐
Hacking with Swift
hackingwithswift.com › example-code › language › how-to-transform-a-dictionary-using-mapvalues
How to transform a dictionary using mapValues() - free Swift example code and tips
May 28, 2019 - Swift version: 5.10 · Paul Hudson @twostraws May 28th 2019 · Although dictionaries have a general map() method, they also have a specialized form of map() called mapValues() – it transforms just the values of the dictionary, leaving the keys untouched. This extra method is useful because dictionaries can’t have duplicate keys, but if you’re only transforming the values from a dictionary then this is not a problem.
🌐
Cocoa Casts
cocoacasts.com › swift-essentials-1-how-to-use-swift-map-to-transforms-arrays-sets-and-dictionaries
How to Use Swift Map to Transform Arrays, Sets, and ...
It returns a dictionary, not an array. In this example, we invoke mapValues(_:) on the dictionary of country codes and country names. We transform the value of each key-value pair to an integer, the number of characters of the country name.
Find elsewhere
🌐
TutorialsPoint
tutorialspoint.com › what-s-the-cleanest-way-of-applying-map-to-a-dictionary-in-swift
What\'s the cleanest way of applying map() to a dictionary in Swift?
In Swift, we can use the map() method to the dictionary to apply a transformation to the values of the dictionary. This method returns a newly created object with the same keys as the original dictionary but with the values transformed by the mapping
🌐
GitHub
gist.github.com › jordanekay › 3e4f46d9f9e0d50c2b7b
Mapping dictionaries in Swift · GitHub
Mapping dictionaries in Swift. GitHub Gist: instantly share code, notes, and snippets.
🌐
Programiz
programiz.com › swift-programming › library › dictionary › mapvalues
Swift Dictionary mapValues() (With Examples)
Swift Dictionary contains() Swift Array map() Swift Dictionary sorted() The mapValues() method transforms the dictionary by applying the same operation to each value in the dictionary.
🌐
Cocoa Casts
cocoacasts.com › swift-fundamentals-how-to-map-an-array-to-a-dictionary
How to Map an Array to a Dictionary
The first solution is the most obvious one. We create a mutable dictionary of type [String: String] and iterate through the sequence of properties that are passed to the send(event:properties:) method.
🌐
CodeVsColor
codevscolor.com › swift dictionary map explanation with example - codevscolor
Swift dictionary map explanation with example - CodeVsColor
August 11, 2020 - If you want a dictionary, you need to convert that array to a dictionary. ... var my_dict = ["one" : 1, "two": 2, "three": 3] var dict_array = my_dict.map{key,value in (key.uppercased(), value*2)} print(dict_array)
🌐
Swift Forums
forums.swift.org › evolution › pitches
Mapping Dictionary keys - Pitches - Swift Forums
June 14, 2018 - It would be nice to have mapKeys<T> and compactMapKeys<T> functions for dictionaries, just as we now have mapValues<T> and compactMapValues<T> in Swift 4.0. The motivation behind this is that there are concrete cases wh…
Top answer
1 of 1
8

There’s no direct way to map the values in a dictionary to create a new dictionary.

You can pass a dictionary itself into map, since it conforms to SequenceType. In the case of dictionaries, their element is a key/value pair:

// double all the values, leaving key unchanged
map(someDict) { (k,v) in (k, v*2) }

But this will result in an array of pairs, rather than a new dictionary. But if you extend Dictionary to have an initializer that takes a sequence of key/value pairs, you could then use this to create a new dictionary:

extension Dictionary {
    init<S: SequenceType where S.Generator.Element == Element>
        (_ seq: S) {
            self.init()
            for (k,v) in seq {
                self[k] = v
            }
    }
}

let mappedDict = Dictionary(map(someDict) { (k,v) in (k, v*2) })
// mappedDict will be [“a”:2, “b”:4, “c”:6]

The other downside of this is that, if you alter the keys, you cannot guarantee the dictionary will not throw away certain values (because they keys may be mapped to duplicates of each other).

But if you are only operating on values, you could define a version of map on the values only of the dictionary, in a similar fashion, and that is guaranteed to maintain the same number of entries (since the keys do not change):

extension Dictionary {
    func mapValues<T>(transform: Value->T) -> Dictionary<Key,T> {
        return Dictionary<Key,T>(zip(self.keys, self.values.map(transform)))
    }
}

let mappedDict = someDict.mapValues { $0 * 2 }

In theory, this means you could do an in-place transformation. However, this is not generally a good practice, it’s better to leave it as creating a new dictionary, which you could always assign to the old variable (note, there’s no version of map on arrays that does in-place alteration, unlike say sort/sorted).

🌐
Carver Code
carvercode.com › home › how to map over a dictionary in swift
How to Map Over a Dictionary in Swift - Carver Code
April 9, 2021 - This function takes in a closure, where you’ll have access to the dictionary item’s value that you can modify. The mapValues(_:) method returns a new dictionary identical to the original, but with new values based on the transform that was applied.
🌐
Swift Forums
forums.swift.org › evolution › pitches
Add compactMapValues to Dictionary - Pitches - Swift Forums
November 28, 2017 - Hi, I’d like to propose about compactMapValues in Dictionary. When I imagine removing nil value from dictionary at first as below, but it doesn’t works. ["1" : "1", "2" : nil, "3" : "3"].flatMap { $0 } // [(key: "2", value: nil), (key: "1", value: Optional("1")), (key: "3", value: Optional("3"))] To avoid this, I’ve heard using reduce like this. let result = ["1": "1", "2": nil, "3": "3"].reduce(into: [String: String]()) { (result, x) in if let value = x.value { result[x.key] = value...