Pitel
08/17/2021, 11:28 AM[A, B, B, B, A, B, B]
(A
and B
are instances of sealed classes). I want to transform it to [[A], [B, B, B], [A], [B, B]]
(so, a list of lists, grouped by classes). How?Benoît Liessens
08/17/2021, 11:31 AMfold()
? Looks like you want to accumulate everything to a List of ListsBenoît Liessens
08/17/2021, 11:38 AMval result = listOf(A, B, B, B, A, B, B)
.fold(mutableListOf(listOf<String>()), { acc, value ->
if (value in acc.last() || acc.last().isEmpty())
acc.apply { add(removeLast() + value) }
else
acc.apply { add(listOf(value)) }
})
Pitel
08/17/2021, 11:40 AMfold
tip! I came up with something similar.Ulrik Rasmussen
08/17/2021, 12:44 PMmutableListOf(listOf<String>).also { acc -> listOf(A, B ...).forEach { ... }}
would sufficeUlrik Rasmussen
08/17/2021, 12:47 PM... + value
operation. This will run in quadratic time in the length of the longest subsequence of repeated elements.Pitel
08/17/2021, 1:05 PMmenu.fold(mutableListOf<MutableList<MenuItem>>()) { list, item ->
when (item) {
is MenuHeader -> {
list.add(mutableListOf(item))
list.add(mutableListOf())
}
is MenuLink -> list.last().add(item)
}
list
}
I did it like this.ephemient
08/17/2021, 4:05 PMinline fun <T, K> Iterable<T>.groupConsecutiveBy(
keySelector: (T) -> K
): List<List<T>> = buildList {
val lastGroup = this@groupConsecutiveBy.fold(mutableListOf<T>()) { acc, value ->
if (acc.isEmpty() || keySelector(acc.last()) == keySelector(value)) {
acc.apply { add(value) }
} else {
add(acc)
mutableListOf(value)
}
}
if (lastGroup.isNotEmpty()) add(lastGroup)
}
ilya.gorbunov
08/31/2021, 12:06 PMephemient
08/31/2021, 7:08 PMgroupBy
in Haskell and itertools.groupby
in Python, but that name's already taken. it's similar to the uniq
command, but I don't think that's a good name. StreamEx calls it groupRuns
, Google Mug calls it groupConsecutiveIf
. I think groupConsecutiveBy
would be reasonable in KotlinUlrik Rasmussen
09/01/2021, 9:03 AMgroupBy
was groupRunsBy
, but I think groupConsecutiveBy
is equally good.ilya.gorbunov
09/02/2021, 2:36 AMilya.gorbunov
09/02/2021, 2:39 AMephemient
09/02/2021, 3:40 AM(Sequence<T>).((T) -> K) -> Sequence<Pair<K, Sequence<T>>>
has some potential for misuse: unless the implementation performs (potentially unbounded) buffering, each subsequence must be consumed at most once before the next, and not at all after the next has started. this contract is clearer in StreamEx's and Mug's use of Stream/Collector, and could be made more obvious with a design like
fun <T, K, R> Sequence<T>.groupConsecutiveByThen(keySelector: (T) -> K, aggregator: (K, Sequence<T>) -> R): Sequence<R>
but that's pretty ugly… of course none of this is a problem for List<T>, just Sequence<T>'ephemient
09/02/2021, 3:50 AM