How do you compare two tables with equal values but different orders?

Okay, so what I want is a little different from every other answer I’ve seen for this on devforum.
Basically, I want to be able to see if two tables with nested tables have equal values but different orders.
So for example, this is table 1.

{
  "a",
  1,
  {"e","2"}
}

And this is table 2.

{
  {"2","e"},
  "a",
  1
}

They both have equal values as you can see, but they have different orders.

Oh and another thing
I don’t want it to be completely random, like values must be equal inside of nested tables.
For example, these two tables won’t work.

t1 = {
  "a",
  1,
  {"e","2"}
}
t2 = {
  "e",
  1,
  {"a","2"}
}

You can something like this:


function areEqualTables(tab1, tab2)
	local equal = true
	for v, i in pairs(tab1) do
		local isIn = false
		for r, e in pairs(tab2) do
			if e == i then
				isIn = true
			end
		end
		if not isIn then
			equal = false
			break
		end
	end
	return equal
end
1 Like

It doesn’t work properly.
As you can see these tables are clearly not the same but it still prints true
image

function areEqualTables(tab1, tab2)
	if #tab1 < #tab2 then
		local new = tab1
		tab1 = tab2
		tab2 = new
	end
	local equal = true
	for v, i in pairs(tab1) do
		local isIn = false
		for r, e in pairs(tab2) do
			if e == i then
				isIn = true
			end
		end
		if not isIn then
			equal = false
			break
		end
	end
	return equal
end

have you tried using the

table.find() 

function to check if the other table has the same value that you detected?

Now it returns false when it should be true

function areEqualTables(tab1, tab2)
	if #tab1 < #tab2 then
		local new = tab1
		tab1 = tab2
		tab2 = new
	end
	local equal = true
	for v, i in pairs(tab1) do
		local isIn = false
		for r, e in pairs(tab2) do
			if e == i then
				isIn = true
			end
		end
		if not isIn then
			equal = false
			break
		end
	end
	return equal
end
local t1={"a","b",{1,2}} 
local t2 = {"b","a",{1,2}} 
print(areEqualTables(t1,t2))

image

First upack the table and the new unpacked table use it in the compare function

function unpackTable(tab)
	local new = {}
	
	for v, i in pairs(tab) do
		table.insert(new, i)
		if type(i) == type({}) then
			local otherTab = unpackTable(i)
			for r, e in pairs(otherTab) do
				table.insert(new, e)
			end
		end
	end
	
	return new
end

print(areEqualTables(unpackTable(t1),unpackTable(t2)))

That won’t work because if we have these two tables

t1 = {
  1,
  2,
  {"a","b"}
}
t2 = {
  1,
  2,
  "a",
  "b"
}

It’ll say both tables are equal when they aren’t

local table1 = {1, 2, 3}
local table2 = {"a", 2, 3}

local function CompareTables(t1, t2)
	if #t1 ~= #t2 then
		return false
	end

	for i = 1, #t1 do
		local v1 = t1[i]
		local v2 = t2[i]
		if v1 ~= v2 then
			return false
		end
	end
	return true
end

print(CompareTables(table1, table2))

Your function has the same problem @ancadejo10 has.
It doesn’t work with nested tables.

local table1 = {1, 2, 3}
local table2 = {{1, 2}, 2, 3}

This printed false for me (with my function)

local table1 = {1, 2, {"b","a"}}
local table2 = {1, 2, {"a","b"}}

local function CompareTables(t1, t2)
	if #t1 ~= #t2 then
		return false
	end

	for i = 1, #t1 do
		local v1 = t1[i]
		local v2 = t2[i]
		if v1 ~= v2 then
			return false
		end
	end
	return true
end

print(CompareTables(table1, table2))

This prints false as well which shouldn’t be the case.

Oh I didn’t know you wanted that. I’ll write something.

Sorting copies of both tables and comparing the values in order should be reasonably fast, so long as elements of the same type are equal when their strings are equal.

local HttpService = game:GetService("HttpService")

local function order(t)
	local copy = {}
	for k, v in pairs(t) do
		copy[k] = type(v) == "table" and order(v) or v
	end
	table.sort(copy, function(a, b)
		if type(a) ~= type(b) then return type(a) > type(b) end
		if type(a) == "table" then
			return HttpService:JSONEncode(a) > HttpService:JSONEncode(b)
		end
		return tostring(a) > tostring(b)
	end)
	return copy
end

function equal(a, b)
	if #a ~= #b then return false end
	local copy_a = order(a)
	local copy_b = order(b)
	for i = 1, #copy_a do
		if type(copy_a[i]) ~= type(copy_b[i]) then return false end
		if type(copy_a[i]) == "table" then
			if not equal(copy_a[i], copy_b[i]) then return false end
		elseif copy_a[i] ~= copy_b[i] then
			return false
		end
	end
	return true
end

example:

local a = {"b", "a", 3, {2, 1}}
local b = {"a", "b", {1, 2}, 3}
print(equal(a, b))

edit: ordering function for tables isn’t necessarily consistent just using tostring, JSONEncode should work though. but really you can just compare both tables that way, so here’s a different equal function

function equal(a, b)
	return HttpService:JSONEncode(order(a)) == HttpService:JSONEncode(order(b))
end

edit: fixed comparing tables directly and returning false after checking if the type is a table

4 Likes

Something like this?

local table1 = {{2, 1}, 2, 3}
local table2 = {{1, 2}, 2, 3}

local function CompareTables(t1, t2)
	if #t1 ~= #t2 then
		return false
	end

	for i = 1, #t1 do
		local v1 = t1[i]
		local v2 = t2[i]
		
		if type(v1) == "table" and type(v2) == "table" then
			return true
		end
		
		if v1 ~= v2 then
			return false
		end
	end
	return true
end

print(CompareTables(table1, table2))

I’ll give some examples of what I want just for future reference.

t1 = {1,2}
t2 = {2,1}
-- true
t1 = {"a","b",{1,2,{1,2}}}
t2 = {{{2,1},2,1},"b","a"}
--true
t1 = {"a","a","b"}
t2 = {"b","a"}
-- false
t1 = {1,{1,5}}
t2 = {1,5,1}
-- false
t1 = {2,1,{3,4}}
t2 = {{4,3},2,1}
--true 
1 Like
function unpackMatrix(matrix)
	local new = {}
	for v, i in pairs(matrix) do
		if type(i) == type({}) then
			local otherTab = unpackMatrix(i)
			for r, e in pairs(otherTab) do
				table.insert(new, e)
			end
		else
			table.insert(new, i)
		end
	end
	return new
end

function compareUnsortedTables(tab1, tab2)
	if #tab1 ~= #tab2 then
		return false
	end
	
	tab1 = unpackMatrix(tab1)
	tab2 = unpackMatrix(tab2)
	
	local equal = true
	for v, i in pairs(tab1) do
		local isIn = false
		for r, e in pairs(tab2) do
			if e == i then
				isIn = true
			end
		end
		
		if not isIn then
			equal = false
			break
		end
	end
	return equal
end

print(compareUnsortedTables(tab1, tab2))

Can you put the non JSONEncode version there as well so others can see?