【发布时间】:2018-09-08 18:09:40
【问题描述】:
我有一个下面的 Kotlin 映射,我想反转映射,对于重复的新键,值将被附加到一个列表中。
val map = Map(1 to 111, 2 to 222, 3 to 111)
转换后的结果图是
Map(111 to List(1,3), 222 to 2)
PS:我确实找到了一种方法,方法是创建一个可变地图并迭代现有地图。但我更多的是寻找一种不可变的方式。
【问题讨论】:
标签: kotlin
我有一个下面的 Kotlin 映射,我想反转映射,对于重复的新键,值将被附加到一个列表中。
val map = Map(1 to 111, 2 to 222, 3 to 111)
转换后的结果图是
Map(111 to List(1,3), 222 to 2)
PS:我确实找到了一种方法,方法是创建一个可变地图并迭代现有地图。但我更多的是寻找一种不可变的方式。
【问题讨论】:
标签: kotlin
您可以根据每个条目的值选择键对映射条目进行分组:
val map = mapOf(1 to 111, 2 to 222, 3 to 111)
val reversed = map.entries.groupBy({ it.value }, { it.key })
println(reversed) // prints: {111=[1, 3], 222=[2]}
【讨论】:
这是一种不使用可变集合的巧妙方法,使用groupingBy,更重要的是aggregate:
val map: Map<Int, Int> = mapOf(1 to 111, 2 to 222, 3 to 111)
val result: Map<Int, List<Int>> = map.entries
.groupingBy { it.value }
.aggregate { key: Int, accumulator: List<Int>?, element: Map.Entry<Int, Int>, first: Boolean ->
if (first) {
listOf(element.key)
} else {
accumulator!! + element.key
}
}
您也可以忽略 first 参数并使用 null 处理来确定您是否已经有一个累加器,当然在任何一种情况下,您都不需要显式键入参数:
val result: Map<Int, List<Int>> = map.entries
.groupingBy { it.value }
.aggregate { key, accumulator, element, first ->
accumulator?.plus(element.key) ?: listOf(element.key)
}
【讨论】:
你应该可以做这样的事情:
fun reverse(map: Map<Int, Int>): Map<Int, List<Int>> {
val mm = mutableMapOf<Int, List<Int>>()
map.forEach { k, v -> mm[v] = mm.getOrDefault(v, listOf()) + k }
return mm
}
它会为您留下一个包含所有地图值的列表,但它确实会反转地图。
【讨论】:
MutableMap 转换为地图?
immutable way of doing it 下是什么意思?虽然目标地图填充了转换后的值,但它必须是可变的。