195

Arrays in Swift support the += operator to add the contents of one Array to another. Is there an easy way to do that for a dictionary?

eg:

var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]

var combinedDict = ... (some way of combining dict1 & dict2 without looping)
Rod
  • 52,748
  • 3
  • 38
  • 55
rustyshelf
  • 44,963
  • 37
  • 98
  • 104

28 Answers28

183

You can define += operator for Dictionary, e.g.,

func += <K, V> (left: inout [K:V], right: [K:V]) { 
    for (k, v) in right { 
        left[k] = v
    } 
}
Dima
  • 23,484
  • 6
  • 56
  • 83
shucao
  • 2,224
  • 1
  • 13
  • 7
  • 1
    Oh man, I struggled so much with finding the proper generic declaration for this, I tried everything except this. But you can drop the `@assignment` and `return`, you're already mutating left. Edit: actually, even though I get no errors, I think `@assignment` should stay. – Roland Jun 09 '14 at 12:02
  • Where do I add this in my code or project in order to use it? I tried adding a separate swift file and I also tried adding it in the class file where I'm trying to use it. – davidethell Jul 05 '14 at 20:22
  • 14
    More syntax sugar: `func += (inout left: [K : V], right: [K : V]) { for (k, v) in right { left[k] = v } }` – Ivan Vavilov Feb 05 '15 at 07:47
  • I don't get it. How should this method be called? ```func += (inout left: [K: V], right: [K: V]){ for (k, v) in right { left[k] = v } } var test = ["1": "a"] += ["2": "b"]``` causes: `Binary operator '+=' cannot be applied to two [String : String] operands`. – Jean Lebrument Sep 04 '15 at 10:01
  • @JeanLebrument you can no more write `var test = ["1": "a"] += ["2": "b"]` than `var test = 2 += 3`. You would write `var test = ["1": "a"] + ["2": "b"]`, and for this to work we would need to write another generic function, which would look like this `func + (left: [K : V], right: [K : V]) -> [K : V]{var new = [K : V](); for (k, v) in right { new[k] = v }; return new }` – sketchyTech Feb 15 '16 at 09:49
  • @DavidRobertson the following code works in Xcode 7.2: `func += (inout left: [K : V], right: [K : V]) { for (k, v) in right { left[k] = v } }` and given a scenario where `var aDict = ["1": "a"]` and `let bDict = ["2": "b"]` we can write `aDict += bDict` – sketchyTech Feb 15 '16 at 09:50
  • @JeanLebrument oops, generic function should be written `func + (left: [K : V], right: [K : V]) -> [K : V]{var new = [K : V](); for (k, v) in left { new[k] = v }; for (k, v) in right { new[k] = v }; return new }` – sketchyTech Feb 15 '16 at 09:56
  • 53
    @animal_chin Because we have to implement half of the language ourselves? Yes. Impressed. Don't get me wrong I love operator overloading. I just don't love having to use it for basic features that should be built in. – devios1 Mar 09 '16 at 20:57
  • 2
    @devios Haha then make it a pull request to the Swift repo :D Since evidently Apple can't be arsed – CommaToast Aug 18 '16 at 19:10
  • 7
    Pulling straight from the [SwifterSwift Library](https://github.com/SwifterSwift/SwifterSwift): ```public static func +=(lhs: inout [Key: Value], rhs: [Key: Value]) { rhs.forEach({ lhs[$0] = $1}) }``` – Justin Oroz Jun 10 '17 at 05:33
  • operators should be `static` :] – pxpgraphics Feb 27 '18 at 23:24
  • That doesn't work for nested dictionaries. imagine this: `["foo", ["foo": 1]]` and `["foo": ["bar": 2]]` – Sepehr Behroozi Jul 31 '18 at 12:54
  • @CommaToast They likely wouldn't accept an overload of `+=`. They decided to forego it for numerics I can't imagine them supporting it for dictionaries. They would probably accept an overload of `+` but it doesn't necessarily handle merge policies. – Dean Kelly Nov 06 '18 at 17:08
131

In Swift 4, one should use merging(_:uniquingKeysWith:):

Example:

let dictA = ["x" : 1, "y": 2, "z": 3]
let dictB = ["x" : 11, "y": 22, "w": 0]

let resultA = dictA.merging(dictB, uniquingKeysWith: { (first, _) in first })
let resultB = dictA.merging(dictB, uniquingKeysWith: { (_, last) in last })

print(resultA) // ["x": 1, "y": 2, "z": 3, "w": 0]
print(resultB) // ["x": 11, "y": 22, "z": 3, "w": 0]
philipp
  • 4,133
  • 1
  • 36
  • 35
Vin Gazoil
  • 1,942
  • 2
  • 20
  • 24
  • 2
    //mutable: var dictA = ["x" : 1, "y": 2, "z": 3] var dictB = ["x" : 11, "y": 22, "w": 0] dictA.merge(dictB, uniquingKeysWith: { (first, _) in first }) print(dictA) // ["x": 1, "y": 2, "z": 3, "w": 0] – muthukumar Feb 15 '18 at 14:56
  • 1
    The second example shown in this answer is the equivalent of `[NSMutableDictionary addEntriesFromDictionary:]`. – orj Apr 13 '18 at 09:27
112

Swift 4 provides merging(_:uniquingKeysWith:), so for your case:

let combinedDict = dict1.merging(dict2) { $1 }

The shorthand closure returns $1, therefore dict2's value will be used when there is a conflict with the keys.

samwize
  • 25,675
  • 15
  • 141
  • 186
  • 1
    Just wanted to point out that this is the most concise and closest I have found to what the Apple documentation states for `- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;`. With regards to what to do with duplicates, it states that: "If both dictionaries contain the same key, the receiving dictionary’s previous value object for that key is sent a release message, and the new value object takes its place.", so in the Swift version, or in merge(_:uniquingKeysWith:), returning the second value, `$1`, is the same as what `addEntriesFromDictionary` does. – Tim Fuqua Jul 16 '18 at 21:27
102

How about

dict2.forEach { (k,v) in dict1[k] = v }

That adds all of dict2's keys and values into dict1.

jasongregori
  • 11,451
  • 5
  • 43
  • 41
  • 48
    Nice solution. Slightly shorter: dict2.forEach { dict1[$0] = $1 } – Brett Feb 17 '17 at 10:19
  • 1
    This a great solution, but for Swift 4, you will most likely get an error stating `Closure tuple parameter '(key: _, value: _)' does not support destructuring` (at least at the time of this writing). One would need to restructure the closure according to [this stackoverflow answer] (https://stackoverflow.com/questions/44945967/closure-tuple-does-not-support-destructuring-in-xcode9-swift4): – JonnyB Dec 04 '17 at 22:11
81

Currently, looking at the Swift Standard Library Reference for Dictionary, there is no way to easy update a dictionary with another one.

You can write an extension to do it

var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]

extension Dictionary {
    mutating func update(other:Dictionary) {
        for (key,value) in other {
            self.updateValue(value, forKey:key)
        }
    }
}

dict1.update(dict2)
// dict1 is now ["a" : "foo", "b" : "bar]
Crashalot
  • 33,605
  • 61
  • 269
  • 439
Rod
  • 52,748
  • 3
  • 38
  • 55
33

It's not built into the Swift library but you can add what you want with operator overloading, e.g:

func + <K,V>(left: Dictionary<K,V>, right: Dictionary<K,V>) 
    -> Dictionary<K,V> 
{
    var map = Dictionary<K,V>()
    for (k, v) in left {
        map[k] = v
    }
    for (k, v) in right {
        map[k] = v
    }
    return map
}

This overloads the + operator for Dictionaries which you can now use to add dictionaries with the + operator, e.g:

var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]

var dict3 = dict1 + dict2 // ["a": "foo", "b": "bar"]
Aviel Gross
  • 9,770
  • 3
  • 52
  • 62
mythz
  • 141,670
  • 29
  • 246
  • 390
  • 1
    You could also do it for += to update in place a dict (as per the op question). – Rod Jun 05 '14 at 05:15
  • 3
    You can do away with `map` and drop the first `for (k, v)...` loop if you declare the `left` parameter as `var` and then just copy values from `right` into it. – Nate Cook Jun 05 '14 at 05:15
  • 2
    @NateCook that would mutate the Dictionary which is not expected behavior for `+` infix operator. – mythz Jun 05 '14 at 05:16
  • Thanks for that. Your answer was probably more accurate to the sample code I posted, while the other one was more what I wanted based on my question. My bad, anyway gave you both an upvote ;) – rustyshelf Jun 05 '14 at 05:36
  • 2
    @mythz It isn't really mutating, since the `+` operator overload isn't a method of either `Dictionary`, it's a simple function. The changes you make to a variable `left` parameter wouldn't be visible outside the function. – Nate Cook Jun 05 '14 at 14:36
  • In case someone else comes across this post and wants both + and +=, note that in the version of Swift included with XCode 6.1.1 does not allow you to include `@infix` before the method definition. – desilvai Mar 10 '15 at 18:08
  • Using `+` is a bad idea since the usual assumption would be that the operator is commutative, which it is most certainly not here. – Raphael Apr 10 '17 at 14:49
28

Swift 3:

extension Dictionary {

    mutating func merge(with dictionary: Dictionary) {
        dictionary.forEach { updateValue($1, forKey: $0) }
    }

    func merged(with dictionary: Dictionary) -> Dictionary {
        var dict = self
        dict.merge(with: dictionary)
        return dict
    }
}

let a = ["a":"b"]
let b = ["1":"2"]
let c = a.merged(with: b)

print(c) //["a": "b", "1": "2"]
Pavel Sharanda
  • 919
  • 10
  • 9
  • 6
    slightly better `func merged(with dictionary: Dictionary) -> Dictionary {` `var copy = self` `dictionary.forEach { copy.updateValue($1, forKey: $0) }` `return copy` `}` – Alexander Vasenin Oct 03 '16 at 01:12
16

Swift 2.0

extension Dictionary {

    mutating func unionInPlace(dictionary: Dictionary) {
        dictionary.forEach { self.updateValue($1, forKey: $0) }
    }

    func union(var dictionary: Dictionary) -> Dictionary {
        dictionary.unionInPlace(self)
        return dictionary
    }
}
olsen
  • 221
  • 3
  • 5
  • can't call a mutating function from a non-mutating function like that – njzk2 Jan 06 '16 at 19:51
  • The `union` function has the value passed into it be a `var`, meaning the copied dictionary can be mutated. It's a bit cleaner than `func union(dictionary: Dictionary) -> Dictionary { var dict2 = dictionary; dict2.unionInPlace(self); return dict2 }`, if only by one line. – MaddTheSane Feb 07 '16 at 03:00
  • 2
    var params are deprecated and will be removed in Swift 3. The preferred way of doing this is now to declare a var in the body: `var dictionary = dictionary`. From here: https://github.com/apple/swift-evolution/blob/master/proposals/0003-remove-var-parameters.md – Daniel Wood Apr 26 '16 at 10:21
  • To make things more type-safe, add `` to those `Dictionary`s. – Raphael Apr 10 '17 at 14:53
15

No need to have any dictionary extensions now. Swift(Xcode 9.0+) dictionary has got a functionality for this. Have a look here. Below here is an example on how to use it

  var oldDictionary = ["a": 1, "b": 2]
  var newDictionary = ["a": 10000, "b": 10000, "c": 4]

  oldDictionary.merge(newDictionary) { (oldValue, newValue) -> Int in
        // This closure return what value to consider if repeated keys are found
        return newValue 
  }
  print(oldDictionary) // Prints ["b": 10000, "a": 10000, "c": 4]
Baig
  • 4,737
  • 1
  • 32
  • 47
Vinayak Parmar
  • 608
  • 10
  • 18
  • 2
    I'm adding a functional style for the above example: `oldDictionary.merge(newDictionary) { $1 }` – Andrej Jan 16 '18 at 15:50
13

Immutable

I prefer to combine/unite immutable dictionaries with + operator so I implemented it like:

// Swift 2
func + <K,V> (left: Dictionary<K,V>, right: Dictionary<K,V>?) -> Dictionary<K,V> {
    guard let right = right else { return left }
    return left.reduce(right) {
        var new = $0 as [K:V]
        new.updateValue($1.1, forKey: $1.0)
        return new
    }
}

let moreAttributes: [String:AnyObject] = ["Function":"authenticate"]
let attributes: [String:AnyObject] = ["File":"Auth.swift"]

attributes + moreAttributes + nil //["Function": "authenticate", "File": "Auth.swift"]    
attributes + moreAttributes //["Function": "authenticate", "File": "Auth.swift"]
attributes + nil //["File": "Auth.swift"]

Mutable

// Swift 2
func += <K,V> (inout left: Dictionary<K,V>, right: Dictionary<K,V>?) {
    guard let right = right else { return }
    right.forEach { key, value in
        left.updateValue(value, forKey: key)
    }
}

let moreAttributes: [String:AnyObject] = ["Function":"authenticate"]
var attributes: [String:AnyObject] = ["File":"Auth.swift"]

attributes += nil //["File": "Auth.swift"]
attributes += moreAttributes //["File": "Auth.swift", "Function": "authenticate"]
ricardopereira
  • 11,118
  • 5
  • 63
  • 81
  • 5
    I don't understand why this isn't built into swift by default? – ioquatix Feb 14 '16 at 13:06
  • 1
    are you intending values from left to override the right in your "Immutable" solution? I think you mean to have `right.reduce(left)`, at least that is the expected behavior imo (and it's the behavior of your second example) - ie. `["A":1] + ["A":2]` should output `["A":2]` – chasew Jun 02 '16 at 17:08
  • The output corresponds to the code. I want the initial value to be the right side, like it is right now. – ricardopereira Jun 02 '16 at 20:45
11

You can try this

var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]

var temp = NSMutableDictionary(dictionary: dict1);
temp.addEntriesFromDictionary(dict2)
shim
  • 9,289
  • 12
  • 69
  • 108
Uttam Kumar
  • 169
  • 1
  • 8
11

A more readable variant using an extension.

extension Dictionary {    
    func merge(dict: Dictionary<Key,Value>) -> Dictionary<Key,Value> {
        var mutableCopy = self        
        for (key, value) in dict {
            // If both dictionaries have a value for same key, the value of the other dictionary is used.           
            mutableCopy[key] = value 
        }        
        return mutableCopy
    }    
}
orkoden
  • 18,946
  • 4
  • 59
  • 50
10

You can also use reduce to merge them. Try this in the playground

let d1 = ["a":"foo","b":"bar"]
let d2 = ["c":"car","d":"door"]

let d3 = d1.reduce(d2) { (var d, p) in
   d[p.0] = p.1
   return d
}
farhadf
  • 1,918
  • 3
  • 19
  • 27
10

Some even more streamlined overloads for Swift 4:

extension Dictionary {
    static func += (lhs: inout [Key:Value], rhs: [Key:Value]) {
        lhs.merge(rhs){$1}
    }
    static func + (lhs: [Key:Value], rhs: [Key:Value]) -> [Key:Value] {
        return lhs.merging(rhs){$1}
    }
}
John Montgomery
  • 6,739
  • 9
  • 52
  • 68
7

I recommend the SwifterSwift Library. However, if you don't want to use the entire library and all its great additions you can just make use of their extension of Dictionary:

Swift 3+

public extension Dictionary {
    public static func +=(lhs: inout [Key: Value], rhs: [Key: Value]) {
        rhs.forEach({ lhs[$0] = $1})
    }
}
Justin Oroz
  • 614
  • 8
  • 14
7

There is no need extension or any extra func anymore. You can write like that :

firstDictionary.merge(secondDictionary) { (value1, value2) -> AnyObject in
        return object2 // what you want to return if keys same.
    }
Burak Dizlek
  • 4,805
  • 2
  • 23
  • 19
  • or indeed `firstDictionary.merge(secondDictionary) { (current, _) in current }` to keep the first value and `firstDictionary.merge(secondDictionary) { (_, new) in new }` to keep the second value if the keys are the same. – hotdogsoup.nl May 25 '22 at 07:38
5

You can iterate over the Key Value combinations ob the value you want to merge and add them via the updateValue(forKey:) method:

dictionaryTwo.forEach {
    dictionaryOne.updateValue($1, forKey: $0)
}

Now all values of dictionaryTwo got added to dictionaryOne.

LeonS
  • 2,684
  • 2
  • 31
  • 36
4

The same as @farhadf's answer but adopted for Swift 3:

let sourceDict1 = [1: "one", 2: "two"]
let sourceDict2 = [3: "three", 4: "four"]

let result = sourceDict1.reduce(sourceDict2) { (partialResult , pair) in
    var partialResult = partialResult //without this line we could not modify the dictionary
    partialResult[pair.0] = pair.1
    return partialResult
}
Dmitry Klochkov
  • 2,484
  • 24
  • 31
4

Swift 3, dictionary extension:

public extension Dictionary {

    public static func +=(lhs: inout Dictionary, rhs: Dictionary) {
        for (k, v) in rhs {
            lhs[k] = v
        }
    }

}
aaannjjaa
  • 338
  • 3
  • 6
4

You can use,

func addAll(from: [String: Any], into: [String: Any]){
    from.forEach {into[$0] = $1}
}
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
3

You can add a Dictionary extension like this:

extension Dictionary {
    func mergedWith(otherDictionary: [Key: Value]) -> [Key: Value] {
        var mergedDict: [Key: Value] = [:]
        [self, otherDictionary].forEach { dict in
            for (key, value) in dict {
                mergedDict[key] = value
            }
        }
        return mergedDict
    }
}

Then usage is as simple as the following:

var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]

var combinedDict = dict1.mergedWith(dict2)
// => ["a": "foo", "b": "bar"]

If you prefer a framework that also includes some more handy features then checkout HandySwift. Just import it to your project and you can use the above code without adding any extensions to the project yourself.

Jeehut
  • 20,202
  • 8
  • 59
  • 80
  • Installing a library to use a single function is bad practice – HackaZach Jul 15 '16 at 17:30
  • @HackaZach: I just updated my answer to include the appropriate part of the framework to prevent inclusion of the entire library if only this little part is needed. I'm keeping the hint to the framework for people who want to use multiple of it's features. I hope this helps keeping good practice! – Jeehut Jul 15 '16 at 20:57
1

You can use the bridgeToObjectiveC() function to make the dictionary a NSDictionary.

Will be like the following:

var dict1 = ["a":"Foo"]
var dict2 = ["b":"Boo"]

var combinedDict = dict1.bridgeToObjectiveC()
var mutiDict1 : NSMutableDictionary! = combinedDict.mutableCopy() as NSMutableDictionary

var combineDict2 = dict2.bridgeToObjectiveC()

var combine = mutiDict1.addEntriesFromDictionary(combineDict2)

Then you can convert the NSDictionary(combine) back or do whatever.

Anton
  • 559
  • 2
  • 15
  • Sorry what do you mean exactly? – Anton Apr 07 '16 at 14:08
  • Just a preference. Seems convoluted to bridge between languages. Better to stick within the confines of a single language, while simultaneously let obj-c die faster. – TruMan1 Apr 07 '16 at 14:10
  • 2
    Yeah, I posted this answer literally on the day Swift announced....... So there was a reason – Anton Apr 07 '16 at 18:03
1

All of these responses are complicated. This is my solution for swift 2.2 :

    //get first dictionnary
    let finalDictionnary : NSMutableDictionary = self.getBasicDict()
    //cast second dictionnary as [NSObject : AnyObject]
    let secondDictionnary : [NSObject : AnyObject] = self.getOtherDict() as [NSObject : AnyObject]
    //merge dictionnary into the first one
    finalDictionnary.addEntriesFromDictionary(secondDictionnary) 
Kevin ABRIOUX
  • 16,507
  • 12
  • 93
  • 99
  • This only works on **NSMutableDictionary** and not native Swift dictionaries, unfortunately. I wish this would be added to Swift natively. – Chris Paveglio Feb 09 '18 at 18:11
1
import Foundation

let x = ["a":1]
let y = ["b":2]

let out = NSMutableDictionary(dictionary: x)
out.addEntriesFromDictionary(y)

The result is an NSMutableDictionary not a Swift typed dictionary, but the syntax to use it is the same (out["a"] == 1 in this case) so you'd only have a problem if you're using third-party code which expects a Swift dictionary, or really need the type checking.

The short answer here is that you actually do have to loop. Even if you're not entering it explicitly, that's what the method you're calling (addEntriesFromDictionary: here) will do. I'd suggest if you're a bit unclear on why that would be the case you should consider how you would merge the leaf nodes of two B-trees.

If you really actually need a Swift native dictionary type in return, I'd suggest:

let x = ["a":1]
let y = ["b":2]

var out = x
for (k, v) in y {
    out[k] = v
}

The downside of this approach is that the dictionary index - however it's done - may be rebuilt several times in the loop, so in practice this is about 10x slower than the NSMutableDictionary approach.

Jim Driscoll
  • 894
  • 11
  • 8
0

My needs were different, I needed to merge incomplete nested data sets without clobbering.

merging:
    ["b": [1, 2], "s": Set([5, 6]), "a": 1, "d": ["x": 2]]
with
    ["b": [3, 4], "s": Set([6, 7]), "a": 2, "d": ["y": 4]]
yields:
    ["b": [1, 2, 3, 4], "s": Set([5, 6, 7]), "a": 2, "d": ["y": 4, "x": 2]]

This was harder than I wanted it to be. The challenge was in mapping from dynamic typing to static typing, and I used protocols to solve this.

Also worthy of note is that when you use the dictionary literal syntax, you actually get the foundation types, which do not pick up the protocol extensions. I aborted my efforts to support those as I couldn't find an easy to to validate the uniformity of the collection elements.

import UIKit


private protocol Mergable {
    func mergeWithSame<T>(right: T) -> T?
}



public extension Dictionary {

    /**
    Merge Dictionaries

    - Parameter left: Dictionary to update
    - Parameter right:  Source dictionary with values to be merged

    - Returns: Merged dictionay
    */


    func merge(right:Dictionary) -> Dictionary {
        var merged = self
        for (k, rv) in right {

            // case of existing left value
            if let lv = self[k] {

                if let lv = lv as? Mergable where lv.dynamicType == rv.dynamicType {
                    let m = lv.mergeWithSame(rv)
                    merged[k] = m
                }

                else if lv is Mergable {
                    assert(false, "Expected common type for matching keys!")
                }

                else if !(lv is Mergable), let _ = lv as? NSArray {
                    assert(false, "Dictionary literals use incompatible Foundation Types")
                }

                else if !(lv is Mergable), let _ = lv as? NSDictionary {
                    assert(false, "Dictionary literals use incompatible Foundation Types")
                }

                else {
                    merged[k] = rv
                }
            }

                // case of no existing value
            else {
                merged[k] = rv
            }
        }

        return merged
    }
}




extension Array: Mergable {

    func mergeWithSame<T>(right: T) -> T? {

        if let right = right as? Array {
            return (self + right) as? T
        }

        assert(false)
        return nil
    }
}


extension Dictionary: Mergable {

    func mergeWithSame<T>(right: T) -> T? {

        if let right = right as? Dictionary {
            return self.merge(right) as? T
        }

        assert(false)
        return nil
    }
}


extension Set: Mergable {

    func mergeWithSame<T>(right: T) -> T? {

        if let right = right as? Set {
            return self.union(right) as? T
        }

        assert(false)
        return nil
    }
}



var dsa12 = Dictionary<String, Any>()
dsa12["a"] = 1
dsa12["b"] = [1, 2]
dsa12["s"] = Set([5, 6])
dsa12["d"] = ["c":5, "x": 2]


var dsa34 = Dictionary<String, Any>()
dsa34["a"] = 2
dsa34["b"] = [3, 4]
dsa34["s"] = Set([6, 7])
dsa34["d"] = ["c":-5, "y": 4]


//let dsa2 = ["a": 1, "b":a34]
let mdsa3 = dsa12.merge(dsa34)
print("merging:\n\t\(dsa12)\nwith\n\t\(dsa34) \nyields: \n\t\(mdsa3)")
Chris Conover
  • 8,889
  • 5
  • 52
  • 68
0

Swift 2.2

func + <K,V>(left: [K : V], right: [K : V]) -> [K : V] {
    var result = [K:V]()

    for (key,value) in left {
        result[key] = value
    }

    for (key,value) in right {
        result[key] = value
    }
    return result
}
apinho
  • 2,235
  • 3
  • 25
  • 39
0

I would just use the Dollar library.

https://github.com/ankurp/Dollar/#merge---merge-1

Merges all of the dictionaries together and the latter dictionary overrides the value at a given key

let dict: Dictionary<String, Int> = ["Dog": 1, "Cat": 2]
let dict2: Dictionary<String, Int> = ["Cow": 3]
let dict3: Dictionary<String, Int> = ["Sheep": 4]
$.merge(dict, dict2, dict3)
=> ["Dog": 1, "Cat": 2, "Cow": 3, "Sheep": 4]
Andrew
  • 3,733
  • 1
  • 35
  • 36
0

Here is a nice extension I wrote...

extension Dictionary where Value: Any {
    public func mergeOnto(target: [Key: Value]?) -> [Key: Value] {
        guard let target = target else { return self }
        return self.merging(target) { current, _ in current }
    }
}

to use:

var dict1 = ["cat": 5, "dog": 6]
var dict2 = ["dog": 9, "rodent": 10]

dict1 = dict1.mergeOnto(target: dict2)

Then, dict1 will be modified to

["cat": 5, "dog": 6, "rodent": 10]