dco*_*led 4 key-value multimap kotlin
我正在寻找一种转换成对列表的惯用方法,其中Pair.first
是键,Pair.second
是值列表。这种过程方法有效,但我希望找到一种更惯用的方法,不需要直接创建可变列表。
val pairs: Pair<String, List<Int>>
val res = mutableMapOf<String, List<Int>>()
pairs.forEach {
res.getOrPut(it.first, ::mutableListOf).addAll(it.second)
}
Run Code Online (Sandbox Code Playgroud)
这段代码可以封装在扩展函数中,如下所示,但它看起来不太通用:
fun <K, V> List<Pair<K, Collection<V>>>.toMultimap(): Map<K, List<V>> {
var res = mutableMapOf<K, MutableList<V>>()
forEach {
res.getOrPut(it.first, ::mutableListOf).addAll(it.second)
}
return res
}
Run Code Online (Sandbox Code Playgroud)
使用pairs.toMap
不起作用,因为它会使用“最后获胜”方法覆盖地图键。 groupBy
工作很接近,它在列表结构的列表中创建值的键。
val pairs2 = listOf(
Pair("a", listOf(1, 2, 3)),
Pair("b", listOf(6, 7)),
Pair("a", listOf(4, 5)),
Pair("b", listOf(8, 9)),
)
val res = pairs2.groupBy({ it.first }, { it.second })
println(res)
Run Code Online (Sandbox Code Playgroud)
{a=[[1, 2, 3], [4, 5]], b=[[6, 7], [8, 9]]}
然后可以展平映射,但缺点是效率相当低,因为这会为每个键创建双倍所需的哈希映射和列表(一个用于 groupby,另一个用于展平)。如果有
val res = pairs2.groupBy({ it.first }, { it.second }).mapValues { it.value.flatten() }
println(res)
Run Code Online (Sandbox Code Playgroud)
{a=[1,2,3,4,5],b=[6,7,8,9]}
看看是否有更好的方法来完成这种转变。
而不是groupBy
使用groupingBy
,它会产生一个Grouping
. 这是一个中间对象,您可以在其上执行各种折叠/缩小操作。在你的情况下:
fun <K, V> List<Pair<K, Collection<V>>>.toMultimap() =
groupingBy { it.first }
.fold(emptyList<V>()) { acc, (_, new) -> acc + new }
Run Code Online (Sandbox Code Playgroud)
+
如果您不喜欢创建太多新列表的事实,您可以执行以下操作:
groupingBy { it.first }
.fold({ _, _ -> mutableListOf<V>() }) { _, acc, (_, new) ->
acc.addAll(new)
acc
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
1751 次 |
最近记录: |