The map() Function in Swift. In Swift, you can use the built-in map() function to modify each element in a collection. The map() function loops through the collection, applying a function for each element. The map() function always returns an array where the transformed values are.
To change the value of a key-value pair, use the . updateValue() method or subscript syntax by appending brackets [ ] with an existing key inside them to a dictionary's name and then adding an assignment operator ( = ) followed by the modified value.
This implementation will include the following functions: put(key, value) : Insert a (key, value) pair into the Dictionary. If the value already exists in the Dictionary, update the value. get(key) : Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key.
Sets are unordered collections of unique values. Dictionaries are unordered collections of key-value associations. Arrays, sets, and dictionaries in Swift are always clear about the types of values and keys that they can store. This means that you can't insert a value of the wrong type into a collection by mistake.
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!
With Swift 5, you can use one of the five following snippets in order to solve your problem.
Dictionary
mapValues(_:)
methodlet 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]
Dictionary
map
method and init(uniqueKeysWithValues:)
initializerlet dictionary = ["foo": 1, "bar": 2, "baz": 5]
let tupleArray = dictionary.map { (key: String, value: Int) in
return (key, value + 1)
}
//let tupleArray = dictionary.map { ($0, $1 + 1) } // also works
let newDictionary = Dictionary(uniqueKeysWithValues: tupleArray)
print(newDictionary) // prints: ["baz": 6, "foo": 2, "bar": 3]
Dictionary
reduce(_:_:)
method or reduce(into:_:)
methodlet 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]
Dictionary
subscript(_:default:)
subscriptlet 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]
Dictionary
subscript(_:)
subscriptlet 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]
While most of the answers here focus on how to map the entire dictionary (keys and values), the question really only wanted to map the values. This is an important distinction since mapping values allows you to guarantee the same number of entries, whereas mapping both key and value might result in duplicate keys.
Here’s an extension, mapValues
, that allows you to map just the values. Note it also extends dictionary with an init
from a sequence of key/value pairs, which is a bit more general than initializing it from an array:
extension Dictionary {
init<S: SequenceType where S.Generator.Element == Element>
(_ seq: S) {
self.init()
for (k,v) in seq {
self[k] = v
}
}
func mapValues<T>(transform: Value->T) -> Dictionary<Key,T> {
return Dictionary<Key,T>(zip(self.keys, self.values.map(transform)))
}
}
The cleanest way is to just add map
to Dictionary:
extension Dictionary {
mutating func map(transform: (key:KeyType, value:ValueType) -> (newValue:ValueType)) {
for key in self.keys {
var newValue = transform(key: key, value: self[key]!)
self.updateValue(newValue, forKey: key)
}
}
}
Checking that it works:
var dic = ["a": 50, "b": 60, "c": 70]
dic.map { $0.1 + 1 }
println(dic)
dic.map { (key, value) in
if key == "a" {
return value
} else {
return value * 2
}
}
println(dic)
Output:
[c: 71, a: 51, b: 61]
[c: 142, a: 51, b: 122]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With