+1 vote

I want to capy my dictionary into another variable and have it not effect the original variable. Currently when i do:

dict_new = my_dict

If I adapt anything in dictnew it also impacts mydict. Is there a way of duplicating the data rather than just referencing it?

in Engine by (285 points)

3 Answers

+3 votes
Best answer

There is no straightforward manner unfortunately. This is because there are multiple ways of cloning such object. You could do a shallow copy, a deep copy, and even the objects you store in it themselves would need to support copy (if it's nodes? If it's resources? If it's a custom class?). And what would even happen if by mistake, your dictionary contains a reference to itself? (circular reference).

But I can give you something that copies recursively, should work for pure data and maybe on some Objects:

static func deep_copy(v):
    var t = typeof(v)

    if t == TYPE_DICTIONARY:
        var d = {}
        for k in v:
            d[k] = deep_copy(v[k])
        return d

    elif t == TYPE_ARRAY:
        var d = []
        d.resize(len(v))
        for i in range(len(v)):
            d[i] = deep_copy(v[i])
        return d

    elif t == TYPE_OBJECT:
        if v.has_method("duplicate"):
            return v.duplicate()
        else:
            print("Found an object, but I don't know how to copy it!")
            return v

    else:
        # Other types should be fine,
        # they are value types (except poolarrays maybe)
        return v

Just make sure your data doesn't contain cycles, or this will hang forever :p

Example:

var demo = {
    hello = 42,
    world = "yolo",
    sub = {
        x = PI,
        y = 12345
    },
    list = [
        "one",
        "two", 
        "three"
    ]
}

print(demo)
var dup = deep_copy(demo)
print(dup)
by (27,166 points)
selected by

Thanks for this

Thanks, really helpful!

+1 vote

I had this issue before and I couldn't find an obvious way to do it. I ended up making a function, e.g:

extends Node

func _ready():

    var my_dict = { "blood":"red", "ink":"black" }
    var my_other_dict = {}

    clone_dict(my_dict, my_other_dict)

    my_dict["slime"] = "green"
    my_other_dict["sky"] = "blue"

    print("my dict:", my_dict)
    print("my other dict:", my_other_dict)

func clone_dict(source, target):
    for key in source:
        target[key] = source[key]

Output is:

my dict:(blood:red), (ink:black), (slime:green)
my other dict:(blood:red), (ink:black), (sky:blue)

Let me know if you find a better way :)

by (51 points)

So my issue with this is I have a rather large dictionary which contains dictionaries within dictionaries. So this function won't make a completely unique dictionary for me like it would if it just contained key:value pairs. Thanks for your reply though. Surely there is some way to make a dictionary unique in a straightforward manner.

+5 votes

I know this is old, but now you can use dict_new = my_dict.duplicate()

by (46 points)
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.

Categories