Oleg Gordiichuk Oleg Gordiichuk - 1 month ago 12
Swift Question

Merge arrays with condition

I would like to merge two arrays with specific condition and update objects that they are containing.

First my struct that is in arrays:

struct Item {
var id:Int
var name:String
var value:Int
}


Second elements for the two arrays:

let fisrt = Item(id: 1, name: "Oleg", value: 3)
let second = Item(id: 2, name: "Olexander", value:5)

let fisrtInSecond = Item(id: 1, name: "Bogdan", value: 6)
let secondInSecond = Item(id: 2, name: "Max", value: 9)


Arrays:

var fisrtArray = [fisrt, second]
let secondArray = [fisrtInSecond, secondInSecond]


I woudl like to use
zip
and
map
functions of the collection to achive result. Result is that
fisrtArray
elements
names
are updated by
id
.

Example:
fisrtArray = [Item(id: 1, name: "Bogdan", value:3), Item(id: 2, name: "Max", value:5)]


I know how to do this via simple loops. But i am looking for more advanced usage of the functional programing is Swift.

My experiment:

fisrtArray = zip(fisrtArray, secondArray).map()


The main problem i do not know how to write condition in the
map
function. Condition should be:

if ($0.id == $1.id) {
$0.name = $1.name
}


From the comment discussing it is possible to highlight that
zip
is not suitable in my case because we should iterate over all array to find if we have similar id's that are not in the same order.

Answer

The following code does work independently by the order of the elements inside the 2 arrays

firstArray = firstArray.map { (item) -> Item in
    guard
        let index = secondArray.index(where: { $0.id == item.id })
        else { return item }
    var item = item
    item.name = secondArray[index].name
    return item
}

"[Item(id: 1, name: "Bogdan", value: 3), Item(id: 2, name: "Max", value: 5)]\n"

Update

The following version uses the first(where: method as suggested by Martin R.

firstArray = firstArray.map { item -> Item in
    guard let secondElm = secondArray.first(where: { $0.id == item.id }) else { return item }
    var item = item
    item.name = secondElm.name
    return item
}