如何在kotlin中将Map列表合并到一个Map?

7z5jn7bk  于 2021-08-20  发布在  Java
关注(0)|答案(4)|浏览(470)

关闭。这个问题需要详细或明确。它目前不接受答案。
**想改进这个问题吗?**编辑这篇文章,添加细节并澄清问题。

21小时前关门。
改进这个问题
我有一个列表<map<enum,set>>我需要得到map<enum,set>
例如,我有:

listOf(mapOf(Enum.First to setOf("one", "two", "three")),
 mapOf(Enum.Second to setOf("four", "five", "six")))

我需要:

mapOf(Enum.First to setOf("one", "two", "three"), Enum.Second to setOf("four", "five", "six"))
kokeuurv

kokeuurv1#

此函数用于将贴图列表展平为单个贴图。请注意,如果存在任何重复的键,则只会显示该键最后一次出现的值。

fun <K, V> flatten(list: List<Map<K, V>>): Map<K, V> =
    mutableMapOf<K, V>().apply {
        for (innerMap in list) putAll(innerMap)
    }

例子:

enum class Enum { First, Second }

fun main() {
    val list = listOf(
        mapOf(Enum.First to setOf("one", "two", "three")),
        mapOf(Enum.Second to setOf("four", "five", "six"))
    )
    val map = flatten(list)
    println(map)
}

输出:

{First=[one, two, three], Second=[four, five, six]}
gwo2fgha

gwo2fgha2#

首先,有一个具体的优化方案 Map 保存枚举键的实现: EnumMap .
不幸的是,kotlin stdlib中没有方便的函数用于 EnumMap 创造(如其他 Map 实现),因此您可以定义自己的(感谢@adam millerchip的想法):

inline fun <reified K : kotlin.Enum<K>, V> enumMapOf() = EnumMap<K, V>(K::class.java)
inline fun <reified K : kotlin.Enum<K>, V> enumMapOf(vararg pairs: Pair<K, V>) = pairs.toMap(EnumMap(K::class.java))

其次,当原始列表中有两个具有相同键(和不同值)的Map时,可能有不同的策略来缓解这种情况:

val list = listOf(
    mapOf(Enum.First to setOf("one", "two", "three")),
    mapOf(Enum.Second to setOf("four", "five", "six")),
    mapOf(Enum.First to setOf("four", "five", "six"))
)

简单的策略是“最新胜利”:

val res = list.fold(enumMapOf<Enum, Set<String>>()) { acc, map ->
    acc.apply { putAll(map) }
}
println(res) // {First=[four, five, six], Second=[four, five, six]}

另一种方法是“合并值”:

val resMerged = list.fold(enumMapOf<Enum, Set<String>>()) { acc, map ->
    map.forEach { (k, v) -> acc.merge(k, v) { old, new -> old.union(new) } }
    acc
}
println(resMerged) // {First=[one, two, three, four, five, six], Second=[four, five, six]}

为方便起见,可以定义用于合并贴图的辅助扩展方法(并使用 union 使用中缀呼叫):

fun <K, V : Any> MutableMap<K, V>.merge(map: Map<K, V>, remappingFunction: (V, V) -> V) {
    map.forEach { (k, v) -> this@merge.merge(k, v, remappingFunction) }
}

val resMerged = list.fold(enumMapOf<Enum, Set<String>>()) { acc, map ->
    acc.apply { merge(map) { old, new -> old union new } }
}
println(resMerged) // {First=[one, two, three, four, five, six], Second=[four, five, six]}
xxhby3vn

xxhby3vn3#

试试这个:

fun getMapOf(listOfMaps: List<Map<Enum, Set<String>>>): Map<Enum, Set<String>> {
    return listOfMaps
        .flatMap { map -> map.entries }
        .associate(Map.Entry<Enum, Set<String>>::toPair)

}
hiz5n14c

hiz5n14c4#

我最初的方法类似于adam millerchip(可变Map和putall)。当列表中的每个Map包含多个条目时,效果会更好。
但是,对于op的特定情况,即列表中每个Map只有一个条目,以下解决方案非常方便:

val map = list.map { it.entries.first().toPair() }.toMap()

在列表和每个 Map 使用 entries.first() 得到它的唯一 Entry 让它成为一个 Pair . 由此产生的 Pair 然后将s转换为 Map .
备选方案,使用关联 associate(transform -> Pair) 通过提供返回 Pair(key, value) .

val map = list.associate { it.entries.first().toPair() }

由于op没有指定如何处理具有相同键的贴图,“如果存在任何重复键,则只会显示该键最后一次出现的值。”
第一个选项的功能示例:

fun <K, V> singleEntryMapListToMap(list: List<Map<K, V>>) =
    list.map {
        it.entries.first().toPair()
    }.toMap()

输出:

{First=[one, two, three], Second=[four, five, six]}

相关问题