How do you add a Dictionary of items into another Dictionary

DictionarySwift

Dictionary Problem Overview


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)

Dictionary Solutions


Solution 1 - Dictionary

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
    } 
}

Solution 2 - Dictionary

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]

Solution 3 - Dictionary

How about

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

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

Solution 4 - Dictionary

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.

Solution 5 - Dictionary

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]

Solution 6 - Dictionary

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"]

Solution 7 - Dictionary

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"]

Solution 8 - Dictionary

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
    }
}

Solution 9 - Dictionary

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]

Solution 10 - Dictionary

#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"]

Solution 11 - Dictionary

You can try this

var dict1 = ["a" : "foo"]
var dict2 = ["b" : "bar"]
        
var temp = NSMutableDictionary(dictionary: dict1);
temp.addEntriesFromDictionary(dict2)

Solution 12 - Dictionary

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
    }    
}

Solution 13 - Dictionary

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
}

Solution 14 - Dictionary

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}
    }
}

Solution 15 - Dictionary

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})
    }
}

Solution 16 - Dictionary

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.

Solution 17 - Dictionary

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.
    }

Solution 18 - Dictionary

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
}

Solution 19 - Dictionary

Swift 3, dictionary extension:

public extension Dictionary {

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

}

Solution 20 - Dictionary

You can use,

func addAll(from: [String: Any], into: [String: Any]){
    from.forEach {into[$0] = $1}
}

Solution 21 - Dictionary

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.

Solution 22 - Dictionary

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.

Solution 23 - Dictionary

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) 

Solution 24 - Dictionary

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.

Solution 25 - Dictionary

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)")

Solution 26 - Dictionary

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
}

Solution 27 - Dictionary

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]

Solution 28 - Dictionary

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]

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrustyshelfView Question on Stackoverflow
Solution 1 - DictionaryshucaoView Answer on Stackoverflow
Solution 2 - DictionaryVin GazoilView Answer on Stackoverflow
Solution 3 - DictionaryjasongregoriView Answer on Stackoverflow
Solution 4 - DictionarysamwizeView Answer on Stackoverflow
Solution 5 - DictionaryRodView Answer on Stackoverflow
Solution 6 - DictionarymythzView Answer on Stackoverflow
Solution 7 - DictionaryPavel SharandaView Answer on Stackoverflow
Solution 8 - DictionaryolsenView Answer on Stackoverflow
Solution 9 - DictionaryVinayak ParmarView Answer on Stackoverflow
Solution 10 - DictionaryricardopereiraView Answer on Stackoverflow
Solution 11 - DictionaryUttam KumarView Answer on Stackoverflow
Solution 12 - DictionaryorkodenView Answer on Stackoverflow
Solution 13 - DictionaryfarhadfView Answer on Stackoverflow
Solution 14 - DictionaryJohn MontgomeryView Answer on Stackoverflow
Solution 15 - DictionaryJustin OrozView Answer on Stackoverflow
Solution 16 - DictionaryLeonSView Answer on Stackoverflow
Solution 17 - DictionaryBurak DizlekView Answer on Stackoverflow
Solution 18 - DictionaryDmitry KlochkovView Answer on Stackoverflow
Solution 19 - DictionaryaaannjjaaView Answer on Stackoverflow
Solution 20 - DictionarySazzad Hissain KhanView Answer on Stackoverflow
Solution 21 - DictionaryJeehutView Answer on Stackoverflow
Solution 22 - DictionaryAntonView Answer on Stackoverflow
Solution 23 - DictionaryKevin ABRIOUXView Answer on Stackoverflow
Solution 24 - DictionaryJim DriscollView Answer on Stackoverflow
Solution 25 - DictionaryChris ConoverView Answer on Stackoverflow
Solution 26 - DictionaryapinhoView Answer on Stackoverflow
Solution 27 - DictionaryAndrewView Answer on Stackoverflow
Solution 28 - DictionaryBrian J. RobertsView Answer on Stackoverflow