Is there a way to split a list in two at a given i...
# getting-started
c
Is there a way to split a list in two at a given index? I tried
partition
but I can't give it a true/false predicate. I just want to give it a location. I tried
slice
but it only gives me a list after the index. I just wanna be able to slice a list into two parts at a given index and get both parts in one shot (that should be more performant than calling slice twice... right?)
y
Just use
sublist
twice. It returns a view on the list, and so it just results in an object allocation. Do keep in mind that sublist does depend on the list, and so if the list updates, the sublists would update, but that can be simply remedied by copying first before `sublist`ing
plus1 2
c
Thanks!
f
you can also use
take
and
drop
,
Copy code
val firstN = list.take(n)
val remainder = list.drop(n)
1
👌 1
p
What was the problem with slice?
Btw is there a way to create an unbounded range to avoid specifying list.size?
c
n until Int.MAX_VALUE
?
😒 1
k
That gives IndexOutOfBoundsException. It occurs to me that String has a substring function that takes one Int argument and returns the substring up to the end. Why is List different?
c
Ah, no,
slice
expects the end limit to be a valid index. Using
take
/`drop` is probably the best, then.
String has a substring function that takes one Int argument and returns the substring up to the end.
That's
List.drop
But yeah, String and List have a lot of differences.
length
/`size` ,
substring
/`subList` …
f
@Pihentagy Follow upvoted solution or feel free to use a listIterator, and use the content while your are iterating, is will be probably the best effort solution
Copy code
list.listIterator()
    .withIndex()
    .forEachRemaining { (index, it) ->
        when {
            index < list.size / 2 -> println("first half")
            else -> println("second half")
        }
    }
m
This is why, locally, we have introduced the concept of
Copy code
val leftBound = n until null
val rightBound = null until n
val open = openRange<Int>() // null until null, typesafe
but I would love for these mathematical properties to exist in kotlin itself as well, we can't live without them
c
I know I can call slice twice or sublist twice. I was hoping there was a method that returned a pair with the first chunk of the list, and the second chunk of the list.
c
Copy code
fun <T> List<T>.partition(n: Int) =
    take(n) to drop(n)
Maybe it's worth making a feature request to the standard lib?
c
have never filed a feature request for kotlin. i might look that up.
c
Just explain what you want here: https://kotl.in/issue Do mention that you know about take/drop, but you'd like a function that does both at once.
If you do create it, please send the link here afterwards, I'd like to subscribe to it
k
I think this does what you want:
Copy code
list.withIndex().partition { it.index <= n }.toList().map { it.map { it.value } }
But it's so unreadable that any of the other solutions are better.
c
↑ it's also much slower: it goes through the list 2 times, whereas the take/drop solution doesn't even go through the list once