Как перевернуть карту в Котлине?
Я пытаюсь перевернуть карту в Котлине. До сих пор я придумал:
mapOf("foo" to 42)
.toList()
.map { (k, v) -> v to k }
.toMap()
есть ли лучший способ сделать это без использования посредника (middlelist)?
3 ответов
С Map
состоит из Entry
S и это не Iterable
. но вы можете использовать карту записи# вместо этого, он будет соответствовать карта № 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}
или используя карта#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())
}