0 votes

Hello, I've been trying to create a function to update dictionay's keys at will. So for instance the functions goes like: update_dict(keypath:string,value).

The keypath has to be something like: "key1/key11/key11_1/result" and the value false for example. The keypath is splitted in a String array using .split("/"). And then I need to check for the first string in the array and if it exist get in, and then repeat the process until the target key is found.

Thing is I need it to search it even if there are a dozen of keys to dive into. The solution I found is not something I think It can be done which is add an extra dictionary[key][key2] + [key ...] every time a key has been found. That beeing said If anyone could help me out please :S

Short mindmap:
-> Input a keypath i.e "key1/key11/key11_1/result" -> Split it into an array -> Check for the first element of the array, and if found check for the next one -> if the target key(the last one of the array) is found -> change it's value -> And If in anywhere on the keypath there's a missing key or wasn't found, throw an error.

    This is a isolated script, no relations.

var dictionary = {
    "key1":{
        "key1_1":{
            "key1_1_1"{
                "result":true,
                "foo":bar
            },
            "key1_1_2":"more example"
        }
    }
    "key2":"example"
}

var keypath: PoolStringArray = ["key1","key1_1","key_1_1_1","foo"] # This is a result of a .split("/")
var i = -1 # Set this to one to start from index 0 on the string array
var last_key

while keypath.size() >= i:
    i += 1
    var next_key = keypath[i] # sets one key ahead,

    if dictionary.has(next_key) && i == 0:
        last_key = next_key
        continue

 # So in the example I gave, the keypath had a size of 4 but
 # if i want to keep searching i need to repeat the elif until
 # it has the same number as the poolstringarray -> more info below

    elif dictionary[last_key].has(next_key) && i > 0:    
        last_key = next_key                                
        continue                                        

    else:
        print("Key not found")
        break

So what I'm trying to see if it's posible is add an extra "[last_key]" here:
dictionary[here][here][here]... until I get to the key I'm looking for...

I don't know if this is posible or if there is a workaround but I've been having headaches trying to solve this...

Any clue on how to do this? I don't want to hard code the elif statement because the database is not done, so I need it to be dynamic in order to have it prepared for any kind of keypath.

ANY clue or guidelines on how should I do it would be apreciatted. I need to find a solution or a workaround that works similar like this, or maybe an example of other's way of achieving it.

Thanks for coming to my ted talk, please send help.

in Engine by (108 points)

1 Answer

0 votes

Hi,
what you need is recursion ...

func set_path(path, value):
    var keypath: PoolStringArray = ["key1","key1_1","key1_1_1","foo"] 
    _set_path(dictionary,keypath,value)

func _set_path(dict,keypath, value):
    var current = keypath[0]
    if dict.has(current):
        if typeof(dict[current]) == TYPE_DICTIONARY:
            keypath.remove(0)
            _set_path(dict[current],keypath, value) # recursion happens here
            return
        else:
            print_debug("found")
            dict[current] = value
            return
    print_debug("not found")
by (4,084 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 Frequently asked questions and 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 [email protected] with your username.