Kotlin-从地图列表到按键分组的地图

时间:2018-11-22 14:28:05

标签: kotlin

我有一个List<Map<Branch,Pair<String, Any>>>想要转换成一个Map<Branch,List<Pair<String, Any>>>

因此,如果我有一个仅包含2个元素的初始列表:

列表

1. branch1 -> Pair(key1,value1)

   branch2 -> Pair(key2,value2)


2. branch1 -> Pair(key1a,value1a)

我想结束:

地图

branch1 -> Pair(key1,value1)

           Pair(key1a,value1a)

branch2 -> Pair(key2,value2)

是一种groupBy,它使用了最初嵌套的地图中所有键的值。

我尝试过

list.groupBy{it-> it.keys.first()} 

,但显然不起作用,因为它仅使用第一个键。我想要同样的方法,但是使用所有键作为单独的值。

在Kotlin中最惯用的方法是什么?我有一个看起来很丑的Java工作版本,但是我很确定Kotlin有很好的方法来做..只是我到目前为止还没有找到它!

有什么想法吗?

谢谢

5 个答案:

答案 0 :(得分:2)

以下内容:

val result =
    listOfMaps.asSequence()
        .flatMap {
          it.asSequence()
        }.groupBy({ it.key }, { it.value })

将为您提供类型为result的{​​{1}},其中包含您所请求的内容。

答案 1 :(得分:1)

我设法写了这个。

data class Branch(val name: String)
data class Key(val name: String)
data class Value(val name: String)


val sharedBranch = Branch("1")
val listOfMaps: List<Map<Branch, Pair<Key, Value>>> = listOf(
        mapOf(sharedBranch to Pair(Key("1"), Value("1")),
                Branch("2") to Pair(Key("2"), Value("2"))),
        mapOf(sharedBranch to Pair(Key("1a"), Value("1a")))
)

val mapValues: Map<Branch, List<Pair<Key, Value>>> = listOfMaps.asSequence()
        .flatMap { map -> map.entries.asSequence() }
        .groupBy(Map.Entry<Branch, Pair<Key, Value>>::key)
        .mapValues { it.value.map(Map.Entry<Branch, Pair<Key, Value>>::value) }

println(mapValues)

是否可以满足您的需求?

答案 2 :(得分:0)

将其提取为扩展功能

private fun <K, V> List<Map<K, V>>.group(): Map<K, List<V>> =
        asSequence().flatMap { it.asSequence() }.groupBy({ it.key }, { it.value })

像这样使用它:

val list = yourListOfMaps
val grouped = list.group()

答案 3 :(得分:0)

val list: List<Map<Branch, Pair<String, Any>>> = listOf() 
val map = list
    .flatMap { it.entries }
    .groupBy { it.key }
    .mapValues { entry -> entry.value.map { it.value } }

答案 4 :(得分:0)

其他所有人都在使用flatMap,但是您也可以考虑使用fold,这是将较大的集合缩小为较小的集合的常用操作。 (例如,您可以将整数列表fold合并为一个和)。

也许其他人会比上面的flatMap版本更容易阅读:

val listOfMaps: List<Map<Key, Value>> = ...

val mergedMaps: Map<Key, Value> = 
  listOfMaps
    .fold(mutableMapOf()) { acc, curr -> 
      acc.putAll(curr)
      acc
    }

上面的代码在做什么:

  • 创建一个新的空地图。这将是acc(即累加器)。
  • 遍历我们的地图列表。
  • 我们获得的每个条目(curr)都是一张地图。调用putAll,将其内容复制到我们的累积地图中。
  • 返回累积图,以便在下一步中再次使用。