首页 > 解决方案 > 如何在 Kotlin 中合并嵌套地图

问题描述

我正在尝试合并 Kotlin 中两个地图的值,但我似乎无法在线找到解决方案。例如,我有这两个具有嵌套地图的地图对象,如下所示。

第一的:{settings={exit={exitMessage=message0}}, 2=2}

第二:{settings={exit={differentMessage=message1, secondMessage=message2}}, 2=zebra}

如您所见,有些键是相同的(例如settingsexit),但有时键是不同的。我想知道如何合并两个 Map 对象,所以最终结果就像

{settings={exit={exitMessage=message0, differentMessage=message1, secondMessage=message2}}, 2=zebra}

我们不能简单地将两个映射“添加”在一起,因为 Kotlin 会覆盖 Map 对象

例如,如果我们将上面的两个对象相加, as first + second,最终结果将是

{settings={exit={differentMessage=message1, secondMessage=message2}}, 2=zebra}

因为exit第二个地图优先exit于第一个地图对象。

标签: kotlin

解决方案


您可以先尝试展平两张地图:

settings.exit.exitMessage=message0
2=2
settings.exit.differentMessage=message1
settings.exit.secondMessage=message2
2=zebra

然后在合并地图后,你会得到这个:

settings.exit.exitMessage=message0
settings.exit.differentMessage=message1
settings.exit.secondMessage=message2
2=zebra

然后通过爆炸键再次重建地图。

完整代码示例:https ://pl.kotl.in/p9BaUVOF3

展平地图

fun flatten(source: Map<String, Any>, target: HashMap<String, Any>, prefix: String = "") {
    for (entry in source) {
        var fullKey = if (prefix.length > 0) prefix + "." + entry.key else entry.key
        if (entry.value is Map<*, *>) {
            flatten(entry.value as Map<String, Any>, target, fullKey)
            continue
        }
        target.put(fullKey, entry.value)
    }
}

分解扁平地图

fun explode(source: Map<String, Any>, target: HashMap<String, Any>) {
    for (entry in source) {
        var targetMap = target
        var keySegments = entry.key.split(".")
        // Rebuild the map
        for (keySegment in keySegments.dropLast(1)) {
            if (targetMap.containsKey(keySegment)) {
                var value = targetMap.get(keySegment)
                if (value is Map<*, *>) {
                    targetMap = value as HashMap<String, Any>
                    continue
                }
            }
            var newNestedMap = HashMap<String, Any>()
            targetMap.put(keySegment, newNestedMap)
            targetMap = newNestedMap
        }
        // Put values into it
        targetMap.put(keySegments.last(), entry.value)
    }
}

推荐阅读