代码之家  ›  专栏  ›  技术社区  ›  Vincent F

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

  •  0
  • Vincent F  · 技术社区  · 7 年前

    我有一个 List<Map<Branch,Pair<String, Any>>> Map<Branch,List<Pair<String, Any>>>

    因此,如果我有一个只有两个元素的初始列表:

    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()} 
    

    但很明显,它不起作用,因为它只使用第一个键。我想要相同的,但使用所有键作为单个值。

    在科特林,最惯用的方法是什么?我有一个丑陋的Java工作版本,但我很肯定Kotlin有一个很好的方法来实现它。。只是到目前为止我还没有找到它!

    有什么想法吗?

    谢谢

    4 回复  |  直到 7 年前
        1
  •  9
  •   Roland    7 年前

    以下是:

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

    我会给你 result Map<Branch,List<Pair<String, Any>>> 与您要求的内容。

        2
  •  4
  •   LeoColman    7 年前
    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 } }
    
        3
  •  1
  •   nyarian    7 年前

    我已经设法写了这个。

    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)
    

    它适合你的需要吗?

        4
  •  1
  •   dherman    6 年前

    其他人都在使用 flatMap 但是你也可以考虑使用 fold 折叠 将整数列表合并为一个和;这里,将地图列表转换为单个地图)。

    也许其他人会发现这比 以上版本:

    val listOfMaps: List<Map<Key, Value>> = ...
    
    val mergedMaps: Map<Key, List<Value>> = 
      listOfMaps
        .fold(mutableMapOf()) { acc, curr ->
          curr.forEach { entry -> acc.merge(entry.key, listOf(entry.value)) { new, old -> new + old } }
          acc
        }
    

    • 创建一个新的空地图。这将是 acc (即,蓄能器)。
    • 反复浏览我们的地图列表。
    • curr )一次。
    • 对于当前映射,运行其每个键/值对。
    • 对于每个键/值,调用 merge ,传递大小为1的列表(包装值)。如果尚未与键关联,则添加该列表;否则,它将附加到已经存在的列表中。
    • 返回累积贴图,以便在下一步中再次使用。
        5
  •  0
  •   Frank Neblung    7 年前

    将其提取到扩展函数中

    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()