Kotlin groupby value as set instead of list

MrN*_*ful 1 kotlin

I'm going to groupby Set<Pair<String,Int>> values to Map<String, Set<Int>> so simply. Find all matching ints for string and create set. I've got solution that works:


setStringInt.stream()
            .collect(
                groupingBy(
                    Projection::stringObj,
                    mapping(Projection::intObj,
                        toSet<Int>())
                )
            )
Run Code Online (Sandbox Code Playgroud)

I've got kind of cleaner:

            .groupBy { it.stringobj }
            .mapValues { it.value.map { it.intobj }.toSet() }
Run Code Online (Sandbox Code Playgroud)

But it's looking quite dirty. Do you have any idea how to simplify this? Am I able to do this without using stream?

Ale*_*nov 8

我认为这更具可读性:

setStringInt.groupBy({ it.first }, { it.second }).mapValues { it.value.toSet() }
Run Code Online (Sandbox Code Playgroud)

使用

inline fun <T, K, V> Iterable<T>.groupBy(
    keySelector: (T) -> K,
    valueTransform: (T) -> V
): Map<K, List<V>>
Run Code Online (Sandbox Code Playgroud)

超载。


mar*_*ran 5

You can just use the Kotlin functions groupBy and then mapValues directly on the Set.

您第一次使用groupByit.first获得Map<String, List<Pair<String, Int>>。然后,您需要映射结果映射的值,以便List<Int>从获得List<Pair<String, Int>>。像这样:

setStringInt.groupBy { it.first }
            .mapValues { entry -> entry.value.map { it.second }.toSet() }
Run Code Online (Sandbox Code Playgroud)

  • OP 解决方案不产生中间数据结构。如果不使用 kotlins `asSequence().groupingBy().fold`,您将必须使用 java 流才能提高效率。如果“mapValues”是 Kotlin 能做的最好的事情——它真的比现代 java 更好吗? (3认同)