https://kotlinlang.org logo
#announcements
Title
# announcements
j

Justin

10/08/2019, 7:45 PM
I’m wondering if there is something that works like
zip
, but instead of returning pairs based on index, it returns pairs based on a predicate. For example:
Copy code
data class A(val id: String)
data class B(val id: String)

val listA: List<A> = listOf(A(“3”), A(“8”))
val listB: List<B> = listOf(B(“8”), B(“2”), B(“4”))

val pairs: List<Pair<A, B>> = listA.someTransformation(listB) { it.id == id }

// ‘pairs’ would contain:
// listOf((A("8"), B("8"))
Would love to know if there’s a best practice around this type of operation?
And to be clear, there could be several matching id’s between the lists (even though there’s only one in my example).
k

karelpeeters

10/08/2019, 7:47 PM
What do you want yo happen if there are multiple?
j

Justin

10/08/2019, 7:50 PM
Oh sorry there will never be multiple matches in listB for a single item in listA. Ids would only appear once per list. When I said multiple, I meant like if listB had an additional element
B("3")
(matching the first element in listA)
Does that make sense?
And in my scenario, there’s more than one property in each data class that I’m matching them against (ruling out the simple “sort-then-zip” approach that would work in my hypothetical)
j

Jason

10/08/2019, 7:57 PM
Like
intersect
that takes a block for the equality test.
Kinda.
j

Justin

10/08/2019, 8:01 PM
Yea, kinda
k

karelpeeters

10/08/2019, 8:04 PM
Cartesian product + filter should do it, unfortunately there's no cartesian product in Kotlin, see https://youtrack.jetbrains.com/issue/KT-13012 and related issues. You'll have to write it yourself:
Copy code
listA.flatMap { a -> listB.map {  b -> a to b }.filter { (a, b) -> f(a,b) }
maybe with a
asSequence()
inbetween.
Another possibility:
Copy code
listA.flatMap { a -> listB.mapNotNull {  b -> if (f(a,b)) a to b else null } }
j

Justin

10/08/2019, 8:05 PM
wow thanks @karelpeeters! let me try these and see if they do what i need
what is the
f
in the first one (i.e.
... f(a,b) }
?
j

Jason

10/08/2019, 8:08 PM
a.id == b.id
j

Justin

10/08/2019, 8:08 PM
oh i see
what do you mean by with a
asSequence()
in between?
a

Alowaniak

10/08/2019, 8:20 PM
listB.asSequence().map...
so that it doesn't actually create a B long list for each
a
which gets mostly `filter`ed out after it
j

Justin

10/08/2019, 8:36 PM
for the first one, i get a type error in the filter on b
it thinks b is a Pair<A, B>, not B
j

Jason

10/08/2019, 8:37 PM
Copy code
>>> listA.flatMap { a -> listB.map {  b -> a to b }.filter { (a, b) -> a.id == b.id }}
res45: kotlin.collections.List<kotlin.Pair<Line_10.A, Line_9.B>> = [(A(id=8), B(id=8))]
j

Justin

10/08/2019, 8:42 PM
ah that works! (i was wrapping the predicate part in { }... still newish to kotlin). thank you both very much!
j

Jason

10/08/2019, 8:43 PM
👍