Skip to content

Instantly share code, notes, and snippets.

@bastman
Last active February 1, 2023 03:15
Show Gist options
  • Save bastman/3f3821ebec89be58a9a1abf127b7adf3 to your computer and use it in GitHub Desktop.
Save bastman/3f3821ebec89be58a9a1abf127b7adf3 to your computer and use it in GitHub Desktop.
kotlin: How to join 2 collections by a foreign key predicate
data class Off(val id: Int, val offName: String)
data class Prop(val id: Int, val propName: String, val offId: Int)
data class Joined(val off: Off, val props: List<Prop>)
fun main(args: Array<String>) {
val offs: List<Off> = listOf(
Off(id = 1, offName = "Off A"),
Off(id = 2, offName = "Off B")
)
val props: List<Prop> = listOf(
Prop(id = 101, propName = "prop A.101", offId = 1),
Prop(id = 102, propName = "prop A.102", offId = 1),
Prop(id = 201, propName = "prop B.201", offId = 2),
Prop(id = 301, propName = "prop C.201", offId = -100)
)
offs
.joinBy(props) { (off,prop) -> off.id == prop.offId }
// or use: .joinBy(props) { it.first.id == it.second.offId }
.map { Joined(off = it.first, props = it.second) }
.map { println(it) }
/*
prints:
Joined(off=Off(id=1, offName=Off A), props=[Prop(id=101, propName=prop A.101, offId=1), Prop(id=102, propName=prop A.102, offId=1)])
Joined(off=Off(id=2, offName=Off B), props=[Prop(id=201, propName=prop B.201, offId=2)])
*/
}
private inline fun <T : Any, U : Any> List<T>.joinBy(collection: List<U>, filter: (Pair<T, U>) -> Boolean): List<Pair<T, List<U>>> = map { t ->
val filtered = collection.filter { filter(Pair(t, it)) }
Pair(t, filtered)
}
@iulian0512
Copy link

i would not call it join, its functionality is similar to C#'s https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.tolookup?view=netcore-3.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment