Hildebrandt Tobias
05/08/2024, 9:02 AM.sublist
that doesn't throw an OutOfBoundsException
and just gives me all it can?
So if I say give me 4 elements from index 2 onwards, but the list has only 5 entries it should just give me back index 2, 3 and 4.Hildebrandt Tobias
05/08/2024, 9:08 AMmyList.sublist(n, myList.size-1).take(m)
CLOVIS
05/08/2024, 9:15 AMfun <T> List<T>.safeSubList(from: Int, to: Int) =
subList(from.coerceIn(indices), to.coerceIn(indices.start, indices.last + 1))
CLOVIS
05/08/2024, 9:15 AMSzymon Jeziorski
05/08/2024, 9:21 AMsize
as follows:
subList(from.coerceAtLeast(0), to.coerceAtMost(size))
CLOVIS
05/08/2024, 9:24 AMCLOVIS
05/08/2024, 9:24 AMSzymon Jeziorski
05/08/2024, 9:46 AMsubList(from.coerceIn(0..size), to.coerceAtLeast(max(from, 0)).coerceAtMost(size))
https://pl.kotl.in/DNMKJkDTsCLOVIS
05/08/2024, 9:47 AMsubList
to behaveHildebrandt Tobias
05/08/2024, 9:59 AMsublist
to throwHildebrandt Tobias
05/08/2024, 10:03 AMif(n < list.size) {
list.subList(n, state.stationList.size - 1).take(m)
}
But I'll probably add an extension function with SJ's answer.Gurgen Nersesyan
05/08/2024, 10:04 AMlist.drop(2)
? Or maybe I didn't get the questioHildebrandt Tobias
05/08/2024, 10:05 AMGurgen Nersesyan
05/08/2024, 10:05 AMHildebrandt Tobias
05/08/2024, 10:06 AMlist.drop(n).take(m)
? Does that throw?Gurgen Nersesyan
05/08/2024, 10:06 AMGurgen Nersesyan
05/08/2024, 10:07 AMHildebrandt Tobias
05/08/2024, 10:07 AMCLOVIS
05/08/2024, 10:07 AMGurgen Nersesyan
05/08/2024, 10:09 AMlist.slice(n..m)
will do, not sure if that throws or notGurgen Nersesyan
05/08/2024, 10:28 AMGurgen Nersesyan
05/08/2024, 10:29 AMGurgen Nersesyan
05/08/2024, 10:29 AMfun <T> List<T>.safeSubList(n: Int, m: Int): List<T> {
val start = min(max(n,0), min(m, this.size))
val end = min(max(start, m), this.size)
return this.subList(start, end)
}
Gurgen Nersesyan
05/08/2024, 10:32 AMSzymon Jeziorski
05/08/2024, 10:33 AMList<T>.slice
body looks like this:
if (indices.isEmpty()) return listOf()
return this.subList(indices.start, indices.endInclusive + 1).toList()
so it's not safe in case of index bounds, and also creates new list as a result.
One other thing to note is that resulting sublist from normal subList
method reflects changes made to the original list, whereas drop
, take
etc create new lists with shallow copy of the data from original list.
So what you actually need depends on the context, I would put it like that:
Do you want sublist to reflect changes made to original list?
Yes:
Do you want implementation to be index safe?
Yes: proposed `list.safeSubList(from, to)`
No: `list.subList(from, to)`
No:
Do you want implementation to be index safe?
Yes:
Is the performance critical?
Yes: `list.safeSubList(from, to).toList()` // or even create yet another extension if you want to avoid SubList wrapping, though it should be cheap as it doesn't copy data
No: above or `take`/`takeLast` + `drop`/`dropLast` combo
No: `list.slice(from, to)`
Szymon Jeziorski
05/08/2024, 10:46 AMtake
/ drop
etc may not be affecting you much if you're working on relatively small collections. After all I would try to be pragmatic about it and think of it not only about in performance's aspect, but rather in wider context having readability and maintainability in mind (on the one hand dedicated extension can be super handy and make your life easier, but one the other, if you have a codebase with 200 of such micro extensions and use them all over the place then could just be an overkill making reading and writing code harder)