Update a Dictionary by iterating on it's keys.

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By MaximoTG98

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/key1_1/key1_1_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/key1_1/key1_1_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.

:bust_in_silhouette: Reply From: klaas

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