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

Marcin Wisniowski

11/10/2019, 11:49 AM
Does anyone have an idiomatic way of checking if the last
n
elements of a list are the same? Currently I have
list.takeLast(n).toSet().size == 1
but I think this could be simpler.
k

Kroppeb

11/10/2019, 12:08 PM
toSet()
won't stop once it finds an element that is different and will use
O(n)
space.
m

Marcin Wisniowski

11/10/2019, 12:14 PM
True, maybe
list.takeLast(n).all { it == list.last() }
is better.
But it still unnecessarily compares the last element to itself.
k

Kroppeb

11/10/2019, 12:15 PM
You could put it in an extension function if it's a thing you need more often.
If you really hate the fact it compares the last element with itself, you could take a sublist that doesn't contain the last element, but it won't make that much of a difference.
m

molikuner

11/10/2019, 1:51 PM
list.takeLast(n).dropLast(1).all { it == list.last() }
t

todd.ginsberg

11/10/2019, 2:26 PM
list.takeLast(n).distinct().size == 1
seems like a nice way to express it.
k

karelpeeters

11/10/2019, 2:38 PM
Except that's slower than
toSet()
for no reason,
distinct() = toSet().toList()
t

todd.ginsberg

11/10/2019, 2:39 PM
Yeah, that's fair.
It's easier to read though, I feel.
👍 1
p

pablisco

11/10/2019, 8:30 PM
You could overload the default
all
to something like:
Copy code
fun <T> List<T>.all(from: Int = 0, f: (T, T) -> Boolean): Boolean {
    for(i in from until (size-1)) if(!f(get(i), get(i + 1))) return false;
    return true
}
Highly efficient (although not pretty). Then you can use it like:
Copy code
list.all(from = n) { a, b -> a == b }
I personally would go with the distinct solution if efficiency is not an issue. This is just a different option.
d

Derek Peirce

11/11/2019, 1:26 AM
Try
!list.takeLast(n).asSequence().distinct().drop(1).any()
, the laziness of sequences will prevent any unnecessary comparisons, and will only store as much as is necessary.