Comparing tables..

Is there an easier way to check if two tables are identical than just looping through every table and seeing if each value is the same?

After much frustration I finally realised that the == operator won’t compare tables…



] lua_run poo = {"hi","bye"}
> poo = {"hi","bye"}...
] lua_run pee = {"hi","bye"}
> pee = {"hi","bye"}...
] lua_run print( poo == pee )
> print( poo == pee )...
false


:C

[lua]
pee = {“hi”,“bi”}
poo = {“hi”,"bi}
print(unpack(pee) == unpack(poo))
[/lua]

Tables and userdata are only equal to themselves (they are passed by reference, checking for equality essentially checks if the references are the same), looping through and comparing keys and values is the only way.

[editline]2nd January 2011[/editline]

Would only work for numerically indexed tables.

Thanks for the help, it’s given me an idea, what about using **[Table.ToString

http://wiki.garrysmod.com/favicon.ico](http://wiki.garrysmod.com/?title=Table.ToString)**? It worked for comparing the two simple tables above but would it work for a larger, non-numerically indexed table?

table.ToString loops through the table anyway.

Ahhh okay, I’ll use unpack and try and change the table I’m using to use numerical keys, thanks guys.

Iterating and comparing the values seems more efficient since you can just break to loop if you find a mismatch.
[lua]
function Equal(tbl1,tbl2)
for k,v in pairs(tbl1) do
if (tbl2[k] != v) then
return false
end
end
return true
end
[/lua]

The problem with this is that tbl2 could contain keys that tbl1 does not and this would still return true as long as all of the key-value pairs in tbl1 were present in tbl2.

[editline]2nd January 2011[/editline]

I think the best way may be to copy table 2 and remove the values from the copy when they are checked, then after the loop check the length of the table. If it is 0 then the two tables are exactly the same.

[lua]util.CRC(glon.encode(t1)) == util.CRC(glon.encode(t2))[/lua]

:v:

Maybe? Probably not efficient.

String comparison is already optimised in Lua with hashing, there is no need for the CRC.

And character by character comparison would be significantly more efficient than first calculating a checksum.

But for a non-integer table I would have to use table.Count to check the length, which would loop through the entirety of both tables again, therefore looping through 3 tables in total, I may aswell use numerical indexes to cut it down to just one loop, but then I could just use unpack which from what I gathered earlier, doesn’t involve looping through the table at all.

And Entoros, that would probably be inefficient for me, I’m decoding a large table of subtables, looping through it and trying to compare each subtable to another small table which I’ve also just decoded, so I’d have to encode each subtable of the large table and compare each with the encoded small table, then decode it if they’re the same… I think it would be simpler just to use numerical indexes & unpack.

I don’t think there is a more efficient way than this for arbitrary tables without subtables.

[lua]function table.Compare( tbl1, tbl2 )
for k, v in pairs( tbl1 ) do
if ( tbl2[k] != v ) then return false end
end
for k, v in pairs( tbl2 ) do
if ( tbl1[k] != v ) then return false end
end
return true
end[/lua]

snip

[editline]2nd January 2011[/editline]

And you can add support for subtables with recursion.

Yeah, here’s one for subtable support.

[lua]function table.Compare( tbl1, tbl2 )
for k, v in pairs( tbl1 ) do
if ( type(v) == “table” and type(tbl2[k]) == “table” ) then
if ( !table.Compare( v, tbl2[k] ) ) then return false end
else
if ( v != tbl2[k] ) then return false end
end
end
for k, v in pairs( tbl2 ) do
if ( type(v) == “table” and type(tbl1[k]) == “table” ) then
if ( !table.Compare( v, tbl1[k] ) ) then return false end
else
if ( v != tbl1[k] ) then return false end
end
end
return true
end[/lua]