Search code examples
godotgdscript

How to Merge Two Dictionaries or Arrays in GDScript (Godot Engine)?


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

Solution

  • 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