Kev
01/19/2024, 7:08 AMYoussef Shoaib [MOD]
01/19/2024, 7:38 AMassociateBy
on one of them, then a map
on the other, pairing it with the matching value from the first onesimon.vergauwen
01/19/2024, 10:40 AMinline fun <A, B, C, Key> Iterable<A>.zipBy(
other: Iterable<B>,
keySelectorA: (A) -> Key,
keySelectorB: (B) -> Key,
combine: (A, B) -> C
): List<C> {
val firstByKey = associateBy(keySelector)
val secondByKey = other.associateBy(keySelector)
return (firstByKey.keys intersect secondByKey.keys)
.map { key -> firstByKey.getValue(it) to secondByKey.getValue(it) }
}
• intersect
creates a Set
of all common Key
• getValue
returns the value for Key
, (and throws NoSuchKeyElementException but that is impossible in this case)
• keySelector maps A
and B
to Key
, in your case id field
• combine allows to transform common value to be transformed in your case ::Pair
.simon.vergauwen
01/19/2024, 10:42 AMYoussef Shoaib [MOD]
01/19/2024, 10:45 AMassociateBy
on one and iterate over the other with mapNotNull
, but I think it's likely an unnecessary optimizatuonsimon.vergauwen
01/19/2024, 10:54 AMpublic inline fun <A, B, C, Key> Iterable<A>.zipBy(
other: Iterable<B>,
keySelectorA: (A) -> Key,
keySelectorB: (B) -> Key,
combine: (A, B) -> C
): List<C> {
val aByKey = associateBy(keySelectorA)
return other.mapNotNull { b ->
val key = keySelectorB(b)
val aOrNull = aByKey[key]
aOrNull?.let { a -> combine(a, b) }
}
}