web-dev-qa-db-ja.com

Kotlinでマップを元に戻す方法は?

Kotlinでマップを反転しようとしています。これまでのところ、私は思いつきました:

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

ミドルマン(ミドルリスト)を使用せずにこれを行うより良い方法はありますか?

17

MapEntrysで構成されており、Iterableではないため、代わりに Map#entries を使用できます。これは Map#entrySet にマップされ、_Set<Entry>_のバックビューを作成します。次に例を示します。

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

[〜#〜]または[〜#〜]Iterable#associate を使用すると、追加のPairsが作成されます。

_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.
_
37
holi-java

これは、不要なガベージ(ペア、中間データ構造、不要なクロージャーなど)を生成せずに、マップを元に戻す単純な拡張関数です。

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とは異なります)

3
bennyl

マップが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>>
        }

1
Yair Galler

私はまだ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())
}
0
Eoin

_m: Map<K, List<V>>_のようなマルチマップを_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'))はマップに変換されます。

これはおそらく中間オブジェクトを作成します。

0
Mike Samuel