Как объединить вложенные карты в Kotlin

#kotlin

#котлин

Вопрос:

Я пытаюсь объединить значения с двух карт в Kotlin, но, похоже, не могу найти онлайн-решение для этого. Например, у меня есть эти два объекта карты, которые имеют вложенные карты, как показано ниже.

Первый: {settings={exit={exitMessage=message0}}, 2=2}

во — вторых: {settings={exit={differentMessage=message1, secondMessage=message2}}, 2=zebra}

Как вы можете видеть, есть некоторые одинаковые клавиши (например settings , и exit ), но иногда клавиши разные. Мне интересно, как я могу объединить два объекта карты, чтобы конечный результат был таким

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

Мы не можем просто «добавить» две карты вместе, потому что Kotlin переопределит объекты карты

Например, если мы добавим два объекта выше, как first second , конечный результат будет просто

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

поскольку exit карта во втором имеет приоритет над объектом exit карты в первом.

Комментарии:

1. Это то, что я пытаюсь выяснить прямо сейчас. В kotlin, когда вы добавляете два объекта карты вместе (например, если я добавляю first и second ), если ключи совпадают (в моем примере ключ равен settings ), Kotlin выбирает значение second maps в key settings для объединенной карты

2. Ой, ой, я прочитал не тот бит. Игнорируйте то, что я только что сказал.

3. Являются ли карты изменяемыми? Было бы намного проще, если бы они были.

4. Да, карты изменчивы

Ответ №1:

Вы можете попробовать сначала сгладить обе карты:

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

Комментарии:

1. Как мне выровнять карты? Кроме того, что вы подразумеваете под взрывом ключей

2. Я не знаю, в частности, для Kotlin, но в целом вы можете сгладить карту, пройдя ее рекурсивно и сохранив найденные значения на другой карте, используя ключи, составленные из ключей с исходной карты. Я попробую немного обновить ответ. Разрыв карты — это обратный процесс.

3. Я добавил подсказку по выравниванию к ответу (хотя кодирование на моем мобильном телефоне).

4. @Mkim175 Я обновил ответ и включил рабочий пример кода.