如何使用不变变换在Kotlin中反转地图

时间:2018-09-08 04:39:52

标签: kotlin

我有一个下面的Kotlin映射,我想反转该映射,对于重复的新密钥,该值将附加到列表中。

val map = Map(1 to 111, 2 to 222, 3 to 111)

转换后,结果图为

Map(111 to List(1,3), 222 to 2)

PS:我确实通过创建可变映射并迭代现有映射来制定出一种实现方法。但我更多地寻找一种不变的方法。

3 个答案:

答案 0 :(得分:2)

您可以通过每个条目的值选择键将地图条目分组:

    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]}

答案 1 :(得分:1)

使用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参数,并使用空值处理来确定是否已经有累加器,当然,在两种情况下,您都无需显式键入参数:

val result: Map<Int, List<Int>> = map.entries
        .groupingBy { it.value }
        .aggregate { key, accumulator, element, first ->
            accumulator?.plus(element.key) ?: listOf(element.key)
        }

答案 2 :(得分:0)

您应该可以执行以下操作:

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
}

它将为您提供所有地图值的列表,但确实会颠倒地图。