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) 
            acc.add(s to 1) 
        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)
            acc.add(t to 1)
        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