user1328035
user1328035

Reputation: 195

Merging two arrays of dictionaries based on a shared value

Let's say I have two arrays of dictionaries:

[["id":"1","color":"orange"],["id":"2","color":"red"]]

and

[["id":"1","fruit":"pumpkin"],["id":"2","fruit":"strawberry"]]

How can I merge these based on "id" so that I get

[["id":"1","color":"orange","fruit":"pumpkin"],["id":"2","color":"red","fruit":"strawberry"]]

We know that the two arrays will be the same length. We don't know if the two arrays will be in the same order.

What's the best way to merge each dictionary in Swift?

Upvotes: 1

Views: 2076

Answers (3)

Alain T.
Alain T.

Reputation: 42133

Swift 4's new Dictionary initializers will let you do some pretty impressive magic including merging such as this:

let a1 = [["id":"1","color":"orange"],["id":"2","color":"red"]]
let a2 = [["id":"1","fruit":"pumpkin"],["id":"2","fruit":"strawberry"]]

let merged = Dictionary((a1+a2).map{($0["id"]!,Array($0))}){$0 + $1}
             .map{Dictionary($1 as [(String,String)]){$1}}

print(merged)
// [["id": "2", "fruit": "strawberry", "color": "red"], ["id": "1", "fruit": "pumpkin", "color": "orange"]]

Upvotes: 0

vadian
vadian

Reputation: 285082

The Swift Standard Library in Xcode 9 introduces merge.

The code filters the corresponding dictionary of array2 with the same id and merges the keys and values into array1:

var array1 = [["id":"1","color":"orange"], ["id":"2","color":"red"]]
var array2 = [["id":"1","fruit":"pumpkin"], ["id":"2","fruit":"strawberry"]]

for (index, item) in array1.enumerated() {
    if let filtered = array2.first(where: {$0["id"]! == item["id"]! }) {
        array1[index].merge(filtered) { (current, _) in current }
    }
}

print(array1)

I don't know if merge is available in Swift 3.2, too

Upvotes: 3

Dennis Vennink
Dennis Vennink

Reputation: 1173

For this answer I'm going to assume that the first Array is mutable:

var xs = [["id": "1", "color": "orange"], ["id": "2", "color": "red"]]
let ys = [["id": "1", "fruit": "pumpkin"], ["id": "2", "fruit": "strawberry"]]

for x in xs.enumerated() {
  for y in ys {
    if x.element["id"] == y["id"] {
      for (key, value) in y {
        if x.element[key] == nil {
          xs[x.offset][key] = value
        }
      }
    }
  }
}

Upvotes: 0

Related Questions