How to performantly check if two dictionaries are the same?

I have a table that’s set up/structured like this:

table[part] = part -- the table will always be a dictionary

then, at the end of the function, I have previousTable = table

How do I check when they’re different? Because that’s the only time the code should run.

I’ve tried:

for i, v in returnedInstancesTable do
	print(previousReturnedInstancesTable[i])
end

but I realized that since this time the table was missing one of the keys of the previous table (one of the keys in the current table was set to nil) it appeared as if they were identical, because all iterations of the loop returned not nil.

So then do I inverse the loop?

for i, v in previousReturnedInstancesTable do
	print(returnedInstancesTable[i])
end

But then these really long tables with hundreds of keys and values each get looped through and checked so many times, and this function is binded to the render step…

Any solutions?
Thanks!

Edit: I usually would have asked the mods to delete this thread since it’s no longer needed, I’ve found ways to avoid having to compare two dictionaries. However, since there are so many great responses, I figured it’s a healthy and nutritional read for some, so I’ll keep it up :grin:

Why would you ever do that?
you may iterate over one dictionary and check if all keys are equal but i dont understand what the point of doing that?
If you are writing a good code with proper typecheck this would never heppen in the first place

1 Like

Basically my function goes like this

local function myFunction()

    local table = someFunction()
    
    if table == previousTable then return end
    
    previousTable = table
    
    -- rest of the function

end

The rest of the function is quite hard on the cpu as well, so I’m making an optimization :D

what is this for exactly? usually the best approach would just be storing a variable for ex. changed = nil which you update when the other table changes. However i do need more details to give you a better idea of what you should do

You can use rawequal(dict1, dict2) to check if the values are the same. Here’s a local func that can help:

local function checkTableEquality(table1: { [any]: any }, table2: { [any]: any }): boolean
	if rawequal(table1, table2) then
		return true
	end
	
	for i, v in pairs(table1) do
		if table2[i] ~= v then
			return false
		end
	end

	for i, v in pairs(table2) do
		if table1[i] ~= v then
			return false
		end
	end

	return true
end

This function will return true if equal

In what case would rawequal return false, but the other two would return true?

This would probably be smarter lol

why was one of the replies deleted?

afaik rawequal wont work here, it compares the entire table and not the values within it

> local a, b = {a = true}, {a = true} print(rawequal(a, b))
  false

in this case table a and table b are different tables (although they share the same content) so they dont equal each other
if you were to remove this one statement from the function then it’ll work properly (aslong as the tables dont have more tables in them that could be different) (also little nitpick, pairs is unnecessary and from my totally reliable tests, slower than using no iterator function)

as for one of the replies - it’s some random kid that thinks he’s smarter than everyone and was being rude

forgot to add but, rawequal’s purpose is to ignore the metamethods of the table

2 Likes

From documentation rawequal really only works on variants which are primitive data types. So in the case you’re storing Roblox defined data types like CFrames, Instances, etc it’ll bypass the rawequal.

1 Like

So I end up doing what I initially suggested in my original post, where I’ll have to check both ways. Got it. (I’ll be using your suggestion up top though, with the changed variable lol)

Why the heck would you use rawequal?
that the exact same as doing table1==table2
it would just check a hash value of a table and would do nothing

In case __eq is defined but that raises questions of what you consider equal. Probably shouldn’t be rawequal.

1 Like

while the usecase is invalid here you are also wrong, rawequal is not the same as == in certain cases
also no need to be rude, kiddo

3 Likes

Actually I was wrong. Initially why rawequal is being used here (since this is copied from my util functions) is because we can use this to override __eq metamethod. It’ll keep the same original functionality while defining more conditions to check for equality.

rawequal would not work with that anyway.
Also no point of giving metatable here anyway

He called me kiddo so i spoke to him in his “egoistical” language.

Anyway
the only way you can compare 2 is to iterate from both tables and check if both of their values are equal the same thing.

local db = true
local tab1 = {}
local tab2 = {}
for i,v in tab1 do 
if tab2[i]~=v then db = false break end
end
if db then
for i,v in tab2 do 
if tab1[i]~=v then db = false break end
end
end

Dictionaries are better to be avoided in such cases honestly.

Y’all, stop fighting :joy:

I’ve tried to write something, but there’s an error in my logic…

local function renderSteppedFunction()

	local returnedInstancesTable = findPartsInSelectionBox() -- gotta have this function called cuz it does more than just return a table
				
	if changed == false then
		return
	end
		
	changed = false
				
	if UserInputService:IsKeyDown(Enum.KeyCode.LeftShift) == false then
		for input, input in boxes do
			if returnedInstancesTable[input] == nil then
				module.RemoveHighlight(input)
				changed = true
			end
		end
	end
		
	for part, part in returnedInstancesTable do
		if part and part.Parent and not boxes[part] then
			module.AddHighlight(part)
			changed = true
		end
	end

end

if it changed gets set to false, it never runs again… :thinking:

this is due to nothing going through the for loop in frame 1, changed gets set to false and then never runs the loop again.

Also; this is not what i mean with the changed variable, i do need to know what the use case for findPartsInSelectionBox() is

otherwise you could just remove the changed variable check here, not the best code though :pensive:

I think in your case it may not be actually beneficial to check if tables are different, but you do you.

Wrote this for a quick way to check if a difference exists, I didn’t test it but it should work fine.

local isdifferent = false
local lastkey1, lastkey2

repeat
    local t1key, t1value = next(t1, lastkey1)
    local t2key, t2value = next(t2, lastkey2)

    if t1key ~= t2key or t1value ~= t2value then
        isdifferent = true
    elseif t1value == nil then break end

    lastkey1, lastkey2 = t1key, t2key

until isdifferent

t1 and t2 are the tables you are comparing.