Curious behavior with Dictionary looping

I ran across some strange behavior involving looping through a dictionary accessed table a bit ago. I coded up a simple example to showcase it. I believe I know vaguely what is causing the behavior but figured I’d write this post in case anyone has a more accurate explanation for it, a better work-around, and/or just a general awareness that this behavior exists.

Here is the example code snippet:

local list = {}
list["Entry1"] = "Value1"
local itr = 1

print("BEGIN")
for key, value in pairs(list) do
	print("itr =", itr,":", key, value)
	list["ABC"] = "non-value"
	itr = itr + 1
end
print("END")

The output I expected when I found ran into this behavior would have been:

BEGIN
itr = 1 : Entry1 Value1
END

However, the output shows that the loop iterated twice:

BEGIN
itr = 1 : Entry1 Value1
itr = 2 : Entry1 Value1
END

And for that matter, it iterated twice on the same key, value pair.
I know that once this is identified as the problem, there are some fairly simple work-arounds:

  • Create a “dummy” copy of the dictionary (perhaps just an array of key names) then iterate over that list instead of the list dictionary which may be modified during iteration
  • Initialize an empty “queue” list which will be appended to over the iteration over the list dictionary, then, after iteration, loop over the “queue” which may store functions to be called than then modify the list.

I’m unsure if either of these solutions are ideal however. And still, I’m left wondering a few questions… Why is it that this loop iterates twice on the same key, value pair? I know it must have something to do with adding a new entry on the first iteration. Could this have something to do with the hash-mapping under the hood of Lua dictionaries? Is it possible for the second iteration’s key, value pair to match the key, value appended during the first iteration? Is there a better work-around than one I’ve listed to get around this issue? Any additional information about this behavior would be appreciated.

Thanks,

--East98

I think I understand. It loops loops through that key twice because it starts with that key, sees that it is first, then inserts another key. Now it is looking to loop through key 2, but the key you just inserted is now key 1, so it loops through the original key again. That might be confusing so here:

--original table
table = {Value1 = "Key1"}

--you loop through:

--sees that the first value is "Key1", prints that, all good.
 --Then we insert a new value and here is the new table:

table = {ABC = "non-value", Value1 = "Key1"}

--now we look for the second key and see that it is also "key1", so it prints that again

This probably happens because pairs doesn’t iterate the dictionary in order that you set it; only number keys are iterated in order. I believe what @XdJackyboiiXd21 said is also correct

1 Like