Как перевернуть карту в Котлине?

Я пытаюсь перевернуть карту в Котлине. До сих пор я придумал:

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

есть ли лучший способ сделать это без использования посредника (middlelist)?

3 ответов


С Map состоит из EntryS и это не Iterable. но вы можете использовать карту записи# вместо этого, он будет соответствовать карта № 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}

или используя карта#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.

вот простая функция расширения, которая отменяет карту-без создания ненужного мусора (например, пары, промежуточные структуры данных и ненужные замыкания )

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)


Я все еще изучаю входы и выходы Котлина, но у меня было то же требование, и с Котлина 1.2 кажется, что вы можете перебирать карту и поэтому 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())
}