groupingBy method
# getting-started
m
groupingBy method
e
that can give total counts but that's different than RLE
m
whops...thought that last two elements were D😫
h
Yep, a simple grouping won't do it, as elements may show up more than once in the run. I was hoping for some clever
``fold``
ing or similar, but have no clue how to implement it elegantly.
m
Copy code
``````listOf("a", "a", "b", "c", "c", "a", "a")
.fold(mutableListOf<Pair<String, Int>>()) { acc, s ->
if (acc.isEmpty() || acc.last().first != s)
else
acc[acc.size-1] = s to acc.last().second + 1
acc
}.toList()``````
Copy code
``````fun <T> Iterable<T>.runLengths() = fold(mutableListOf<Pair<T, Int>>()) { acc, t ->
acc.apply {
if (acc.isEmpty() || acc.last().first != t)
else
acc[acc.size-1] = t to acc.last().second + 1
}
}.toList()

listOf("a", "a", "b", "c", "c", "a", "a")
.runLengths()``````
e
there's not any good reason to use a fold there - you're never changing what acc references
m
🙂
Copy code
``````fun <T> Iterable<T>.runLengths() = mutableListOf<Pair<T, Int>>().run {
for (t in this@runLengths)
if (isEmpty() || last().first != t) add(t to 1) else set(size - 1, t to last().second + 1)
toList()
}

listOf("a", "a", "b", "c", "c", "a", "a").runLengths()``````
Or rather
Copy code
``````fun <T> Iterable<T>.runLengths() = buildList<Pair<T, Int>> {
for (t in this@runLengths)
if (isEmpty() || last().first != t) add(t to 1) else set(size - 1, t to last().second + 1)
}

listOf("a", "a", "b", "c", "c", "a", "a").runLengths()``````
e
I think my https://kotlinlang.slack.com/archives/C0B8MA7FA/p1638746141245300?thread_ts=1638744707.244600&amp;cid=C0B8MA7FA has advantages as it doesn't generate more garbage than necessary and can be easily adapted to work as Sequence<T>.() -> Sequence<Pair<T, Int>>, but works either way
🙌 1