For comparison purposes, here's a short but inefficient solution written in the functional style using fold()
:
fun <E> List<E>.mergeConsecutive(): List<Pair<E, Int>>
= fold(listOf()) { acc, e ->
if (acc.isNotEmpty() && acc.last().first == e) {
val currentTotal = acc.last().second
acc.dropLast(1) + (e to currentTotal + 1)
} else
acc + (e to 1)
}
The acc
umulator builds up the list of pairs, incrementing its last entry when we get a duplicate, or appending a new entry when there's a different item. (You could make it slightly shorter by replacing the currentTotal
with a call to let()
, but that would be even harder to read.)
It uses immutable Lists and Pairs, and so has to create a load of temporary ones as it goes — which makes this pretty inefficient ((²)), and I wouldn't recommend it for production code. But hopefully it's instructive.