Assigning array as value in dictionary not working as expected

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

Trying to apply procedural generation in my project, but I’ve got confused with dictionary. I’m certainly doing something wrong. I’m inserting current_tile which is a vector2 (as a key) and var block_combination which is array of one or two numbers (as a value). Code is inside while loop and works as intended on first go, but something not right happens on the next goes and output shows that dictionary gets the key but value is assigned onto the first of the keys and rest of the values in keys changes into this weird array with ellipsis inside. I would really appreciate any input.

This is the code:

if (clear_tile == 0 or next_tile in empties) and one_after in unvisited and not block_combination.has(0):
	Map.set_cellv(next_tile, 4)
	print("chose empty")
	if neighbours.size()> 1 and not block_combination.has(2):
		block_combination.append(0)
		blocks_c[current_tile] = block_combination
		print("current_tile : ", current_tile)
		print("block_combination : ", block_combination)
		print("blocks_c current's tile value: ", blocks_c[current_tile])
		print("all of blocks_c: ", blocks_c)
		print("blocks_c's keys: ", blocks_c.keys())
		print("blocks_c's values:  ", blocks_c.values())
		blocks_d[current_tile] = direction
	current_tile = next_tile
	next_tile = one_after
	empties.append(current_tile)
else:
	print("got to Ds")
	if not block_combination.has(2):
		var two_ways = cell_walls[direction]
		var lucky_dip = randi() % 2
		var d_a  = direction_after[two_ways[lucky_dip+2]]
		if next_tile + d_a in unvisited:
			print("turn d1")
			Map.set_cellv(next_tile, two_ways[lucky_dip])
			if neighbours.size() > 1:
				if not block_combination.has(1):
					block_combination.append(1)
				blocks_c[current_tile] = block_combination
				blocks_d[current_tile] = direction
				print("current_tile : ", current_tile)
				print("block_combination : ", block_combination)
				print("blocks_c current's tile value: ", blocks_c[current_tile])
				print("all of blocks_c: ", blocks_c)
				print("blocks_c's keys: ", blocks_c.keys())
				print("blocks_c's values:  ", blocks_c.values())
				print("block d1 given")
			current_tile = next_tile
			next_tile = next_tile + d_a
			direction = d_a
			unvisited.erase(current_tile)
		else:
			if lucky_dip == 1:
				lucky_dip = 0
			else:
				lucky_dip = 1
			var d_a2  = direction_after[two_ways[lucky_dip+2]]
			if next_tile + d_a2 in unvisited:
				print("turn d2")
				Map.set_cellv(next_tile, two_ways[lucky_dip])
				if neighbours.size()> 1 and not block_combination.has(0):
					block_combination.append(2)
					blocks_c[current_tile] = block_combination
					blocks_d[current_tile] = direction
					print("current_tile : ", current_tile)
					print("block_combination : ", block_combination)
					print("blocks_c current's tile value: ", blocks_c[current_tile])
					print("all of blocks_c: ", blocks_c)
					print("blocks_c's keys: ", blocks_c.keys())
					print("blocks_c's values:  ", blocks_c.values())
					print("block d2 given")
				current_tile = next_tile
				next_tile = next_tile + d_a2
				direction = d_a2
				unvisited.erase(current_tile)

And this is output:

got to clear
chose empty
current_tile : (6, 2)
block_combination : [0]
blocks_c current’s tile value: [0]
all of blocks_c: {(6, 2):[0]}
blocks_c’s keys: [(6, 2)]
blocks_c’s values: [[0]]
current tile is: (5, 2)
neighbours are: [(5, 1), (5, 3), (4, 2)]
next tile is:(4, 2)
got to clear
chose empty
current_tile : (5, 2)
block_combination : [0]
blocks_c current’s tile value: [0]
all of blocks_c: {(5, 2):[…], (6, 2):[0]}
blocks_c’s keys: [(6, 2), (5, 2)]
blocks_c’s values: [[0], […]]
got to clear
got to Ds
turn d1
current_tile : (4, 2)
block_combination : [1]
blocks_c current’s tile value: [1]
all of blocks_c: {(4, 2):[…], (5, 2):[…], (6, 2):[1]}
blocks_c’s keys: [(6, 2), (5, 2), (4, 2)]
blocks_c’s values: [[1], […], […]]
block d1 given

The ... you are getting are probably a string containing "...". But hard to tell where it comes from, it’s from outside the code you posted.

I don’t know where the problem would be in your code, but:

which is array of one or two numbers (as a value).

Keep in mind arrays are reference types, regardless. If you store an array in a dictionary without making it unique (using duplicate), modifying that array later will reproduce the same change everywhere you stored it (because it’s all referring to the same array).

So when you do:

var d = {}
var a = [1, 2, 3]
d["test"] = a
print("Before: ", d)
a.append(4)
print("After: ", d)

You will get:

Before: {test:[1, 2, 3]}
After: {test:[1, 2, 3, 4]}

See how the array in the dictionary also changed, because it is the same array.
But if you do:

var d = {}
var a = [1, 2, 3]
d["test"] = a.duplicate()
print("Before: ", d)
a.append(4)
print("After: ", d)

You will get:

Before: {test:[1, 2, 3]}
After: {test:[1, 2, 3]}

Because the array inside the dictionary is a copy of the array before it was modified later.

Zylann | 2020-04-05 21:41

Thank you for replying and trying to help me with the problem. I understand what you are saying but that is not where the problem is. If you look at that part of the output:

currenttile : (4, 2)
blockcombination : [1]
blocksc current’s tile value: [1]
all of blocksc: {(4, 2):[…], (5, 2):[…], (6, 2):[1]}

Especially the last line should really look like this: all of blocksc: {(4, 2):[1], (5, 2):[0], (6, 2):[0]}. But it looks like it is only applying value to the first (created) key (which is (6,2)) and creating those strange arrays inside any new keys. Even if for some reason the output is showing them as this, it shouldn’t be applying the value only to the first created key. You can see that from code and output that tile is changing and value is changing but output shows that it is applied only to the first created key of the dictionary, while changing others to those ellipsis ones.

I’ve changed blockcombination from array to regular variable and it doesn’t give me that problem. Will see if I can work around that code like that. But I still would like to know why did it behaved like that.

aya9 | 2020-04-06 10:56