I am trying to make a function that takes in a table and a tuple of more tables. What I want to do with these tables is, if they are dictionaries, check if the dictionaries contain the same keys. So I am trying to see if they equal each other basically. I tried this method, but remembered dictionaries aren’t ordered so I knew I had to take a different approach.
-- Bad method
function TableUtil:Equals(tab1,...)
local tab1 = HttpService:JSONEncode(tab1)
for _,tab in pairs({...}) do
if tab == nil or tab1 ~= HttpService:JSONEncode(tab) then
return false
end
end
return true
end
I came to the conclusion that I needed to do this recursively, but I am stuck on how I would exactly do it. There are barely to none resources about this online for Roblox. How can I do this recursively?
If you say dictionaries I will assume you have strings as keys.
Simple method, might not be optimal.
function check(d1, d2)
for k, v in pairs(d1) do
if d2[k] != v then return false end
end
for k, v in pairs(d2) do
if d1[k] != v then return false end
end
return true
end
EDIT: My code checks if the dictionaries have the same values too. If you are interested in keys only then check if non-nil values correspond to non-nil values.
EDIT: as @nicemike40 pointed out pairs works for both scenarios.
Yeah sorry I meant to say values as well, but wouldn’t it get a little messy if the values were tables then I would have to recursively check those tables and/or dictionaries right? no?
function deepcompare(t1, t2, ignore_mt)
local ty1 = type(t1)
local ty2 = type(t2)
if ty1 ~= ty2 then return false end
-- non-table types can be directly compared
if ty1 ~= 'table' and ty2 ~= 'table' then return t1 == t2 end
-- as well as tables which have the metamethod __eq
local mt = getmetatable(t1)
if not ignore_mt and mt and mt.__eq then return t1 == t2 end
for k1, v1 in pairs(t1) do
local v2 = t2[k1]
if v2 == nil or not deepcompare(v1, v2) then return false end
end
for k2, v2 in pairs(t2) do
local v1 = t1[k2]
if v1 == nil or not deepcompare(v1, v2) then return false end
end
return true
end
Which you could use like
function TableUtil:Equals(tab1, ...)
for _, t in pairs({...}) do
if (not deepcompare(tab1, t, true)) then
return false
end
end
return true
end
edit: This will work but it’s pretty dumb If you really need to compare arbitrary numbers of tables at once, it would probably be better to generalize deepcompare so you’re comparing all the tables at each level. That way, you wouldn’t be doing as much unnecessary comparisons.
That doesn’t make any sense. If you have table a, and table b, and they are the same, the JSON strings will be the same. If the tables are different, they will not be the same.