3

Say I have two Dictionaries (or could be Arrays), each having sub-dictionaries (or sub-arrays):

var dict_A = {'a': 1, 'sub_dict':  {'hello': 'world', 'quick': 'fox'}}
var dict_B = {'b': 2, 'sub_dict': {'hello': 'godot'}}

Is there a builtin method in GDScript to merge them, including the sub-dictionaries or sub-arrays?

Expected result would be:

merge_dict(dict_A, dict_B)

# {'a': 1, 'b': 2, 'sub_dict':  {'hello': 'godot', 'quick': 'fox'}}
Renato Byrro
  • 3,578
  • 19
  • 34

1 Answers1

3

There's no builtin method in GDScript for that, but you can use the following functions (find usage examples, unit tests, and more on this Github gist):

Observation: when using deep_merge=true with merge_array, all sub-dictionaries and sub-arrays must be JSON serializable.

func merge_array(array_1: Array, array_2: Array, deep_merge: bool = false) -> Array:
    var new_array = array_1.duplicate(true)
    var compare_array = new_array
    var item_exists

    if deep_merge:
        compare_array = []
        for item in new_array:
            if item is Dictionary or item is Array:
                compare_array.append(JSON.print(item))
            else:
                compare_array.append(item)

    for item in array_2:
        item_exists = item
        if item is Dictionary or item is Array:
            item = item.duplicate(true)
            if deep_merge:
                item_exists = JSON.print(item)

        if not item_exists in compare_array:
            new_array.append(item)
    return new_array


func merge_dict(dict_1: Dictionary, dict_2: Dictionary, deep_merge: bool = false) -> Dictionary:
    var new_dict = dict_1.duplicate(true)
    for key in dict_2:
        if key in new_dict:
            if deep_merge and dict_1[key] is Dictionary and dict_2[key] is Dictionary:
                new_dict[key] = merge_dict(dict_1[key], dict_2[key])
            elif deep_merge and dict_1[key] is Array and dict_2[key] is Array:
                new_dict[key] = merge_array(dict_1[key], dict_2[key])
            else:
                new_dict[key] = dict_2[key]
        else:
            new_dict[key] = dict_2[key]
    return new_dict

This code is licensed under BSD 3-Clause License | Copyright 2022 Hackverse.org

Renato Byrro
  • 3,578
  • 19
  • 34
  • There's a good chance you don't need a license for that piece of code, btw. I'm not a lawyer, but logic would suggest that there should be a limit in simplicity, where no copyright would protect code. Otherwise `print("Hello world")` would be a copyright infringement. It's great you care about sharing the licenses you find, though! – erikbstack Mar 10 '23 at 13:39
  • Also, could you mark this response as the solution? No new suggestions in a year means it's definitely good to mark your own answer. +1 – erikbstack Mar 10 '23 at 13:40