https://kotlinlang.org logo
#getting-started
Title
# getting-started
j

Jérémy CROS

03/27/2024, 4:41 PM
Collections question for you guys 🙂 I have a model that for simplification is a segment with a level and a set of coordinates And I have a list of those segments What I'm looking to do is based on a "current" segment, find all the previous segments that are on the same level until I find one that's on a different level And then flatmap all the coordinates in a list while preserving the order Sort of as a path to the current segment that's on the same level (hopefully that makes sense 😅) What I have so far is that:
Copy code
listOfSegments
    .takeWhile { it != current }
    .reversed()
    .takeWhile { it.level() == current.level() }
    .reversed()
    .flatMap { it.coordinates }
It works but seems rather inefficient. Any idea on how I could improve that?
j

Jacob

03/27/2024, 5:15 PM
Consider starting with a dropwhile
Dropwhile the level is wrong Take until current
Also might help to throw in an asSequence
k

Klitos Kyriacou

03/27/2024, 5:26 PM
What Jacob said will probably work well, but if you want something similar to what you already have, you can avoid creating new intermediate lists using functions that return views over the original list:
Copy code
listOfSegments
    .subList(0, listOfSegments.indexOf(current))
    .asReversed()
    .let { list -> list.subList(0, list.indexOfFirst { it.level() != current.level() } }
    .asReversed()
    .flatMap { it.coordinates }
This can be further simplified:
Copy code
listOfSegments
    .subList(0, listOfSegments.indexOf(current))
    .run { subList(indexOfLast { it.level() != current.level() } + 1, size }
    .flatMap { it.coordinates }
v

Vlad Mircan

03/27/2024, 6:06 PM
@Jérémy CROS Just giving my two cents here, the main issue performance wise here is the
reversed()
calls. Without doing anything complex, we can improve the performance (and readability) of the code a lot by doing this:
Copy code
listOfSegments
    .takeWhile { it != current }
    .takeLastWhile { it.level() == current.level() }
    .flatMap { it.coordinates }
j

Jérémy CROS

03/28/2024, 8:47 AM
takeLastWhile
, that's the one I was looking for! Thanks @Vlad Mircan, I knew there was something better than my double reversed 😅 Thanks @Klitos Kyriacou for the suggestion but the use case is iterating over rather small list so readability is still important and the solution with
takeLastWhile
is easier to understand IMO And thanks @Jacob too but the use case is slightly more complicated than that 😉 the level could be wrong then right then wrong then right then current and I want just the last right before current Anyway, thanks all, I think I'm all good! 🙏
👍 3
3 Views