我有一个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()