Does anyone have an idiomatic way of checking if t...
# announcements
m
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
toSet()
won't stop once it finds an element that is different and will use
O(n)
space.
m
True, maybe
list.takeLast(n).all { it == list.last() }
is better.
But it still unnecessarily compares the last element to itself.
k
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
list.takeLast(n).dropLast(1).all { it == list.last() }
t
list.takeLast(n).distinct().size == 1
seems like a nice way to express it.
k
Except that's slower than
toSet()
for no reason,
distinct() = toSet().toList()
t
Yeah, that's fair.
It's easier to read though, I feel.
👍 1
p
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
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.