Kotlin-从地图列表到按键分组的地图

  • 本文关键字:地图 列表 Kotlin- kotlin
  • 更新时间 :
  • 英文 :


我有一个List<Map<Branch,Pair<String, Any>>>,我想将其转换为单个Map<Branch,List<Pair<String, Any>>>

因此,如果我有一个只有两个元素的初始列表:

列出

1. branch1 -> Pair(key1,value1)
branch2 -> Pair(key2,value2)

2. branch1 -> Pair(key1a,value1a)

我想以结束

映射

branch1 -> Pair(key1,value1)
Pair(key1a,value1a)
branch2 -> Pair(key2,value2)

因此是一种groupBy,使用最初嵌套映射中键的所有值。。

我试过

list.groupBy{it-> it.keys.first()} 

但显然它不起作用,因为它只使用了第一个键。我想要相同的,但使用所有键作为单独的值。

在科特林,最惯用的方法是什么?我有一个丑陋的Java工作版本,但我很确定Kotlin有一个很好的方法…只是到目前为止我还没有找到它!

知道吗?

感谢

以下内容:

val result =
listOfMaps.asSequence()
.flatMap {
it.asSequence()
}.groupBy({ it.key }, { it.value })

将为您提供类型为Map<Branch,List<Pair<String, Any>>>result以及您要求的内容。

val list: List<Map<Branch, Pair<String, Any>>> = listOf() 
val map = list
.flatMap { it.entries }
.groupBy { it.key }
.mapValues { entry -> entry.value.map { it.value } }

其他人都在使用flatMap,但您也可以考虑使用fold,这是将较大集合缩减为较小集合的常见操作。(例如,可以将整数列表fold转换为单个和;这里,将映射列表转换为单个映射(。

也许其他人会发现这比上面的flatMap版本更容易阅读:

val listOfMaps: List<Map<Key, Value>> = ...
val mergedMaps: Map<Key, List<Value>> = 
listOfMaps
.fold(mutableMapOf()) { acc, curr ->
curr.forEach { entry -> acc.merge(entry.key, listOf(entry.value)) { new, old -> new + old } }
acc
}

上面的代码在做什么:

  • 创建一个新的空映射。这将是acc(即累加器(
  • 反复浏览我们的地图列表
  • 一次处理一个地图(curr(
  • 对于当前映射,请遍历其每个键/值对
  • 对于每个键/值,在acc上调用merge,传入一个大小为1的列表(包装值(。如果还没有任何内容与密钥相关联,则添加该列表;否则,它将被附加到已经存在的列表中
  • 返回累积贴图,以便在下一步中再次使用

我已经成功地写下了这篇文章。

data class Branch(val name: String)
data class Key(val name: String)
data class Value(val name: String)

val sharedBranch = Branch("1")
val listOfMaps: List<Map<Branch, Pair<Key, Value>>> = listOf(
mapOf(sharedBranch to Pair(Key("1"), Value("1")),
Branch("2") to Pair(Key("2"), Value("2"))),
mapOf(sharedBranch to Pair(Key("1a"), Value("1a")))
)
val mapValues: Map<Branch, List<Pair<Key, Value>>> = listOfMaps.asSequence()
.flatMap { map -> map.entries.asSequence() }
.groupBy(Map.Entry<Branch, Pair<Key, Value>>::key)
.mapValues { it.value.map(Map.Entry<Branch, Pair<Key, Value>>::value) }
println(mapValues)

它适合你的需要吗?

令人惊讶的是,没有人提到关联函数。

val listy: List<Map<String, Int>> = 
listOf(mapOf("A" to 1, "B" to 2), mapOf("C" to 3, "D" to 4))

val flattened = listy
.flatMap { it.asSequence() }
.associate { it.key to it.value }
println(flattened)

将打印出{A=1, B=2, C=3, D=4}

将其提取到扩展函数

private fun <K, V> List<Map<K, V>>.group(): Map<K, List<V>> =
asSequence().flatMap { it.asSequence() }.groupBy({ it.key }, { it.value })

像这样使用:

val list = yourListOfMaps
val grouped = list.group()

最新更新