35

我正在尝试在 Kotlin 中反转 Map。到目前为止,我想出了:

mapOf("foo" to 42)
  .toList()
  .map { (k, v) -> v to k }
  .toMap()

在不使用中间人(中间人)的情况下,有没有更好的方法呢?

4

5 回答 5

58

由于sMapEntrys 组成,因此Iterable您可以使用Map#entries代替。它将被映射到Map#entrySet以创建 的支持视图Set<Entry>,例如:

val reversed = map.entries.associateBy({ it.value }) { it.key }

使用Iterable#associate,这将创建额外Pair的 s。

val reversed = map.entries.associate{(k,v)-> v to k}

使用Map#forEach

val reversed = mutableMapOf<Int, String>().also {
    //     v-- use `forEach` here     
    map.forEach { (k, v) -> it.put(v, k) } 
}.toMap()
// ^--- you can add `toMap()` to create an immutable Map.
于 2017-07-28T18:40:38.610 回答
6

这是一个反转映射的简单扩展函数 - 不会产生不需要的垃圾(如对、中间数据结构和不必要的闭包)

fun <K, V> Map<K, V>.reversed() = HashMap<V, K>().also { newMap ->
    entries.forEach { newMap.put(it.value, it.key) }
}

请注意,它apply是内联的,并且entries.forEach也是内联的(这对于 是不一样的Map::forEach

于 2017-08-04T10:54:35.017 回答
3

如果您的地图不是 1-1 映射并且您希望反转是值列表:

mapOf(1 to "AAA", 2 to "BBB", 3 to "BBB").toList()
        .groupBy { pair -> pair.second } // Pair<Int, String>
        .mapValues { entry -> 
          entry.value.map { it.first } // Entry<String, List<Pair<Int, String>>
        }

于 2019-10-28T11:14:21.090 回答
2

如果您需要将多图反转m: Map<K, List<V>>为 a ,Map<V, List<K>>您可以这样做

m
  .flatMap { it.value.map { oneValue -> oneValue to it.key } }
  .groupBy({ it.first }, { it.second })
  .toMap()

按顺序,

  • mapOf('a' to listOf('b', 'c'), 'd' to listOf('b')) 得到平面映射到类似的序列
  • listOf('b' to 'a', 'c' to 'a', 'b' to 'd')它被分组到
  • listOf('b' to listOf('a', 'd'), 'c' to listOf('a'))然后将其转换为地图。

这可能会创建中间对象。

于 2019-11-19T15:28:53.417 回答
1

我仍在学习 Kotlin 的来龙去脉,但我有相同的要求,从 Kotlin 1.2 开始,您似乎可以迭代 Map,因此 map() 直接像这样:

@Test
fun testThatReverseIsInverseOfMap() {
    val intMap = mapOf(1 to "one", 2 to "two", 3 to "three")
    val revMap = intMap.map{(k,v) -> v to k}.toMap()
    assertTrue(intMap.keys.toTypedArray() contentEquals revMap.values.toTypedArray())
    assertTrue(intMap.values.toTypedArray() contentEquals revMap.keys.toTypedArray())
}
于 2018-06-14T21:05:23.150 回答