Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a new list from two other lists of different types by comparing values of each type

I have two Lists of objects that both implement an interface, but are otherwise unrelated. How can I create a new collection of objects containing only the objects of one of the lists that match a value in the other list?

Obviously I could use a for loop & do this manually, but I'd like to know how I can do this using Kotlin's standard library collection filtering functions.

So here's an example:

interface Ids
{
    val id: Int
}

data class A(override val id: Int, val name: String) : Ids
data class B(override val id: Int, val timestamp: Long) : Ids

fun main(args: Array<String>) {
    val a1 = A(1, "Steve")
    val a2 = A(2, "Ed")
    val aCol = listOf(a1, a2)

    val b2 = B(2, 12345)
    val b3 = B(3, 67890)
    val bCol = listOf(b2, b3)

    val matches = mutableListOf<B>()
    // This is where I'm stuck.
    // I want to filter bCol using objects from aCol as a filter.
    // The result should be that matches contains only a single object: b2
    // because bCol[0].id == aCol[1].id
    // I'm guessing I need to start with something like this:
    bCol.filterTo(matches) { ??? }
}
like image 514
Jordan Avatar asked Jun 28 '17 23:06

Jordan


1 Answers

A straightforward approach would be to search aCol for an object with the same id for each b in bCol:

bCol.filter { b -> aCol.any { a -> a.id == b.id } }

However that may become too slow if your lists are big enough.

To make it more scalable you can first build a set of all ids in aCol:

val aColIds = aCol.map { it.id }.toSet()

And then use Set.contains method to determine whether b.id is in aColIds:

bCol.filter { it.id in aColIds }
// or equivalent
bCol.filter { aColIds.contains(it.id) }
like image 157
Ilya Avatar answered Oct 22 '22 10:10

Ilya