Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to merge two lists of objects based on IDs?

Tags:

kotlin

I have two lists. One is called oldList and contains old data, the 2nd one is called updateList and contains a set of updates.

I want to create a new list with those rules:

  • take all data from the oldList
  • append all updates with unique id
  • if id of an updated item already exists in oldData, replace it

I came up with a simple code:

Item.kt

data class Item (val id: String, val text: String)

Main.kt

fun main() {

    val oldList: List<Item> = listOf(
        Item("aaa1", "aaa2"),
        Item("bbb1", "bbb2"),
        Item("ddd1", "ddd2"))

    val updateList: List<Item> = listOf(
        Item("aaa1", "aaa3"),
        Item("ccc1", "ccc2"))

    val resultList = oldList.toMutableList()

    for (item in updateList) {
        val index = oldList.indexOfFirst { it.id == item.id }
        if (index < 0) {
            resultList.add(item)
        } else {
            resultList[index] = item
        }
    }

    println(resultList)
}

This works fine but I can imagine it's inefficient and there might also be some nice Kotlin idiom. Is there a better solution?

like image 214
mickp Avatar asked Nov 11 '19 14:11

mickp


People also ask

How do you combine two lists of objects?

One way to merge multiple lists is by using addAll() method of java. util. Collection class, which allows you to add the content of one List into another List. By using the addAll() method you can add contents from as many List as you want, it's the best way to combine multiple List.

How do you merge two lists of objects in Python?

In python, we can use the + operator to merge the contents of two lists into a new list. For example, We can use + operator to merge two lists i.e. It returned a new concatenated lists, which contains the contents of both list_1 and list_2.

How do I merge two arrays of objects in Node JS?

To merge elements from one array to another, we must first iterate(loop) through all the array elements. In the loop, we will retrieve each element from an array and insert(using the array push() method) to another array. Now, we can call the merge() function and pass two arrays as the arguments for merging.


2 Answers

If the original order doesn't matter, you can combine the lists, putting the new values first to favor them in a distinctBy call:

val resultList = (updateList + oldList).distinctBy(Item::id)

If the order matters exactly as you described it, you can convert both lists to maps before combining them. When combining two Maps with +, the items in the second Map take precedence, but the order from the first Map is preserved.

val resultList = 
    (oldList.associateBy(Item::id) + updateList.associateBy(Item::id)).values.toList()
like image 181
Tenfour04 Avatar answered Oct 13 '22 16:10

Tenfour04


You can use the distinctBy method:

val resultList = (updateList + oldList).distinctBy { it.id }

What distinctBy does is return a new list containing only elements having distinct keys returned by the provided lambda. You must bear in mind however that the order of elements matters and the first encountered item with the given key is kept in the result list, the others are ignored.

like image 42
jsamol Avatar answered Oct 13 '22 15:10

jsamol