How to check if two tables(objects) have the same value in Lua
There is no built-in function for comparing tables by contents.
You'll have to write your own. You'll need to decide whether you want to compare tables by contents shallowly or deeply. See https://web.archive.org/web/20131225070434/http://snippets.luacode.org/snippets/Deep_Comparison_of_Two_Values_3 for some ideas.
I offer some improvements for Rutrus solution.
function equals(o1, o2, ignore_mt)
if o1 == o2 then return true end
local o1Type = type(o1)
local o2Type = type(o2)
if o1Type ~= o2Type then return false end
if o1Type ~= 'table' then return false end
if not ignore_mt then
local mt1 = getmetatable(o1)
if mt1 and mt1.__eq then
--compare using built in method
return o1 == o2
end
end
local keySet = {}
for key1, value1 in pairs(o1) do
local value2 = o2[key1]
if value2 == nil or equals(value1, value2, ignore_mt) == false then
return false
end
keySet[key1] = true
end
for key2, _ in pairs(o2) do
if not keySet[key2] then return false end
end
return true
end
Be aware that this solution doesn't take into account self references. You may use pequals (below). It's usefull when you have some tricks in your code. But do not use this method for regular checks! It's slower. Also if your object has self reference, you should reanalyze your structure. Self references can be a sign of bad architecture.
local function internalProtectedEquals(o1, o2, ignore_mt, callList)
if o1 == o2 then return true end
local o1Type = type(o1)
local o2Type = type(o2)
if o1Type ~= o2Type then return false end
if o1Type ~= 'table' then return false end
-- add only when objects are tables, cache results
local oComparisons = callList[o1]
if not oComparisons then
oComparisons = {}
callList[o1] = oComparisons
end
-- false means that comparison is in progress
oComparisons[o2] = false
if not ignore_mt then
local mt1 = getmetatable(o1)
if mt1 and mt1.__eq then
--compare using built in method
return o1 == o2
end
end
local keySet = {}
for key1, value1 in pairs(o1) do
local value2 = o2[key1]
if value2 == nil then return false end
local vComparisons = callList[value1]
if not vComparisons or vComparisons[value2] == nil then
if not internalProtectedEquals(value1, value2, ignore_mt, callList) then
return false
end
end
keySet[key1] = true
end
for key2, _ in pairs(o2) do
if not keySet[key2] then
return false
end
end
-- comparison finished - objects are equal do not compare again
oComparisons[o2] = true
return true
end
function pequals(o1, o2, ignore_mt)
return internalProtectedEquals(o1, o2, ignore_mt, {})
end
Also you may analyze CompareTables on lua wiki.
If you actually want to test simple tables try this...
function do_tables_match( a, b )
return table.concat(a) == table.concat(b)
end
On a separate note, something that compares to your specific example as follows...
function is_table_empty( table_to_test )
-- Doesn't work
return table_to_test == {}
-- Works only if the table is numeric keyed with no gaps
return #table_to_test = 0
-- Works!
return next( table_to_test ) ~= nil
end