合并具有相似外部键的嵌套映射,保留两个内部映射的键值对
Merge nested maps with similar outer keys, keeping both inner map's key value pairs
我想按照下面的方式合并两个嵌套地图,而不覆盖外部地图值的数据,或者通过替换内部地图并覆盖已经存在的数据。
理想情况下,在嵌套地图中,我会保留我已有的 key/value 对,并在第二张地图中添加。
val mapOne: MutableMap<String, MutableMap<String, String>> = mutableMapOf(
"DirectoryOne" to mutableMapOf(
"FeatureOne" to "SomeUniqueStringFeature1",
"FeatureTwo" to "SomeUniqueStringFeature2"
)
)
val mapTwo: MutableMap<String, MutableMap<String, String>> = mutableMapOf(
"DirectoryOne" to mutableMapOf(
"FeatureThree" to "SomeUniqueStringFeature3"
)
)
我需要的结果如下所示:
val mapOne: MutableMap<String, MutableMap<String, String>> = mutableMapOf(
"DirectoryOne" to mutableMapOf(
"FeatureOne" to "SomeUniqueStringFeature1",
"FeatureTwo" to "SomeUniqueStringFeature2",
"FeatureThree" to "SomeUniqueStringFeature3"
)
)
只是为了详细说明这背后的一些原因。我计划在运行时动态构建地图,并将功能添加到单个地图,因为它们需要在整个应用程序持续时间内添加。
我能够使用以下代码执行所需的操作。迭代外部 key/value 对并将嵌套的 key/value 对与 BiConsumer/BiFunction 合并到 mapOne。 (打字有点累)
mapTwo.forEach(BiConsumer { k: String, v: MutableMap<String, String> ->
mapOne.merge(k, v,
BiFunction { v1: MutableMap<String, String>, v2: MutableMap<String, String> ->
v1.putAll(v2)
v1
})
})
我很快发现我可以更轻松地使用 lambda(删除 BiConsumer/BiFunction),然后将 lambda 移出合并括号。最终最优解如下图
mapTwo.forEach { (k: String, v: MutableMap<String, String>) ->
mapOne.merge(k, v
) { v1: MutableMap<String, String>, v2: MutableMap<String, String> ->
v1.putAll(v2)
v1
}
}
我将上面的代码片段包装在 function/method 中,以便能够在需要的地方多次应用它。
如果想避免Java8合并功能的尴尬使用,可以使用getOrPut
。由于函数内联,这也更有效。
此外,根据 Kotlin coding conventions,最好使用常规 for
循环而不是 forEach
(除非您在可空对象上或在集合运营商链)。
for ((key, map) in mapTwo) {
mapOne.getOrPut(key, ::mutableMapOf).putAll(map)
}
广义:
fun <K1, K2, V> MutableMap<in K1, MutableMap<K2, V>>.mergeIn(other: Map<out K1, Map<out K2, V>>) {
for ((key, map) in other) {
getOrPut(key, ::mutableMapOf).putAll(map)
}
}
我想按照下面的方式合并两个嵌套地图,而不覆盖外部地图值的数据,或者通过替换内部地图并覆盖已经存在的数据。
理想情况下,在嵌套地图中,我会保留我已有的 key/value 对,并在第二张地图中添加。
val mapOne: MutableMap<String, MutableMap<String, String>> = mutableMapOf(
"DirectoryOne" to mutableMapOf(
"FeatureOne" to "SomeUniqueStringFeature1",
"FeatureTwo" to "SomeUniqueStringFeature2"
)
)
val mapTwo: MutableMap<String, MutableMap<String, String>> = mutableMapOf(
"DirectoryOne" to mutableMapOf(
"FeatureThree" to "SomeUniqueStringFeature3"
)
)
我需要的结果如下所示:
val mapOne: MutableMap<String, MutableMap<String, String>> = mutableMapOf(
"DirectoryOne" to mutableMapOf(
"FeatureOne" to "SomeUniqueStringFeature1",
"FeatureTwo" to "SomeUniqueStringFeature2",
"FeatureThree" to "SomeUniqueStringFeature3"
)
)
只是为了详细说明这背后的一些原因。我计划在运行时动态构建地图,并将功能添加到单个地图,因为它们需要在整个应用程序持续时间内添加。
我能够使用以下代码执行所需的操作。迭代外部 key/value 对并将嵌套的 key/value 对与 BiConsumer/BiFunction 合并到 mapOne。 (打字有点累)
mapTwo.forEach(BiConsumer { k: String, v: MutableMap<String, String> ->
mapOne.merge(k, v,
BiFunction { v1: MutableMap<String, String>, v2: MutableMap<String, String> ->
v1.putAll(v2)
v1
})
})
我很快发现我可以更轻松地使用 lambda(删除 BiConsumer/BiFunction),然后将 lambda 移出合并括号。最终最优解如下图
mapTwo.forEach { (k: String, v: MutableMap<String, String>) ->
mapOne.merge(k, v
) { v1: MutableMap<String, String>, v2: MutableMap<String, String> ->
v1.putAll(v2)
v1
}
}
我将上面的代码片段包装在 function/method 中,以便能够在需要的地方多次应用它。
如果想避免Java8合并功能的尴尬使用,可以使用getOrPut
。由于函数内联,这也更有效。
此外,根据 Kotlin coding conventions,最好使用常规 for
循环而不是 forEach
(除非您在可空对象上或在集合运营商链)。
for ((key, map) in mapTwo) {
mapOne.getOrPut(key, ::mutableMapOf).putAll(map)
}
广义:
fun <K1, K2, V> MutableMap<in K1, MutableMap<K2, V>>.mergeIn(other: Map<out K1, Map<out K2, V>>) {
for ((key, map) in other) {
getOrPut(key, ::mutableMapOf).putAll(map)
}
}