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

If you had more than one table in a and b then sorting by tostring wouldn’t guarantee that the indices correspond, so the order needs to be based on some serialization of the tables.

This code:


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(t1, t2))

Took me a little bit but I think I did it! All those came out correct

t1 = {"a","b",{1,2,{1,2,3}}}
t2 = {{{2,1},2,1},"b","a"}
local function CompareTables(t1, t2)
	local function hasTable(tab)
		for i, v in pairs(tab) do
			if type(v) == "table" then
				return true
			end
		end
		return false
	end
	
	local function compare(t1, t2)
		if #t1 ~= #t2 then
			return false
		end

		local equalTables = true
		for i, v in pairs(t1) do
			if type(v) == "table" and hasTable(t2) then
				for i, x in pairs(t2) do
					if type(x) == "table" then
						equalTables = compare(v, x)
					end
				end
			elseif type(v) ~= "table" then	
				if not table.find(t2, v) then
					return false
				end	
			end
		end	
		return equalTables
	end
	
	return compare(t1, t2)
end

print(CompareTables(t1, t2))

Still not working.
This should print true, but it prints false.

local t1 = {{"a",2},{"b",2}}
local t2 = {{"b",2},{"a",2}}
print(require(game.ServerStorage.MainModule).comparetablesamevalues(t1,t2))

@1waffle1, your function works but there’s a very random and weird “cooldown” time between every calling, so it’s unusuable.

1 Like

It doesn’t work properly.
This prints true.

function compareUnsortedTables(tab1, tab2)
	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
	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

local t1 = {{"a",1,{}},{"b",1,{}}}
local t2 = {{"b",1,{}},{"a",2,{}}}
print(compareUnsortedTables(t1,t2))

I just tried your new version, it returns fall when both tables are literally exactly the same.

function comparetablesamevalues(a, b)
	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
	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" and not comparetablesamevalues(copy_a[i], copy_b[i]) then return false end
		if copy_a[i] ~= copy_b[i] then return false end
	end
	return true
end

local t1 = {{"a",1,{}},{"b",2,{}}}
local t2 = {{"a",1,{}},{"b",2,{}}}
print(comparetablesamevalues(t1,t2))

image

So far none of the code everyone has given me has worked properly. Aww man.

Apparently even this is false

function comparetablesamevalues(a, b)
	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
	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" and not comparetablesamevalues(copy_a[i], copy_b[i]) then return false end
		if copy_a[i] ~= copy_b[i] then return false end
	end
	return true
end

local t1 = {{"a"}}
local t2 = {{"a"}}
print(comparetablesamevalues(t1,t2))

image

Maybe try this?

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

local function CompareTables(t1, t2)
	local function hasTable(tab)
		for i, v in pairs(tab) do
			if type(v) == "table" then
				return true
			end
		end
		return false
	end
	
	local function compare(t1, t2)
		if #t1 ~= #t2 then
			return false
		end

		local equalTables = true
		for i, v in pairs(t1) do
			if type(v) == "table" and hasTable(t2) then
				local matched = false
				for i, x in pairs(t2) do
					if type(x) == "table" and not matched then
						equalTables = compare(v, x)
						if equalTables == true then
							matched = true
						end
					end
				end
			elseif type(v) ~= "table" then	
				if not table.find(t2, v) then
					return false
				end	
			end
		end	
		return equalTables
	end
	
	return compare(t1, t2)
end

print(CompareTables(t1, t2))

It would print this as true

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

local function CompareTables(t1, t2)
	local function hasTable(tab)
		for i, v in pairs(tab) do
			if type(v) == "table" then
				return true
			end
		end
		return false
	end

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

		local equalTables = true
		for i, v in pairs(t1) do
			if type(v) == "table" and hasTable(t2) then
				local matched = false
				for i, x in pairs(t2) do
					if type(x) == "table" and not matched then
						equalTables = compare(v, x)
						if equalTables == true then
							matched = true
						end
					end
				end
			elseif type(v) ~= "table" then	
				if not table.find(t2, v) then
					return false
				end	
			end
		end	
		return equalTables
	end

	return compare(t1, t2)
end

print(CompareTables(t1, t2))

As you can see they are different

!

local function CompareTables(t1, t2)
	local function hasTable(tab)
		for i, v in pairs(tab) do
			if type(v) == "table" then
				return true
			end
		end
		return false
	end
	
	local function compare(t1, t2)
		if #t1 ~= #t2 then
			return false
		end

		local equalTables = true
		local matches = {}
		for i, v in pairs(t1) do
			if type(v) == "table" and hasTable(t2) then
				for i, x in pairs(t2) do
					if type(x) == "table" and not table.find(matches, x) then
						equalTables = compare(v, x)
						matches[#matches + 1] = x
					end
				end
			elseif type(v) ~= "table" then	
				if not table.find(t2, v) then
					return false
				end	
			end
		end	
		return equalTables
	end
	
	return compare(t1, t2)
end

print(CompareTables(t1, t2))

This returns true

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

local function CompareTables(t1, t2)
	local function hasTable(tab)
		for i, v in pairs(tab) do
			if type(v) == "table" then
				return true
			end
		end
		return false
	end

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

		local equalTables = true
		local matches = {}
		for i, v in pairs(t1) do
			if type(v) == "table" and hasTable(t2) then
				for i, x in pairs(t2) do
					if type(x) == "table" and not table.find(matches, x) then
						equalTables = compare(v, x)
						matches[#matches + 1] = x
					end
				end
			elseif type(v) ~= "table" then	
				if not table.find(t2, v) then
					return false
				end	
			end
		end	
		return equalTables
	end

	return compare(t1, t2)
end

print(CompareTables(t1, t2))

If you don’t care about preserving the order of the two tables, you can use the table.sort function on both tables then comparing them normally.

But, there are nested tables

You could handle those with recursion.

local otherEqual 
otherEqual = function(tableOne, tableTwo)
	--sort both tables
	--loop through each element, looking for equality
		--when you come across a table, use otherEqual(tableOne[index], tableTwo[index])
end

Generally it’s important to consider your use case when making functions like this. Often there is a simpler/better solution specific to your case.

That’s what I tried. Unfortunately, it doesn’t work.

local function CompareTables(t1, t2)
	for i=1,#t1 do
		if not (type(t1[i])=="table") then
			if not table.find(t2,t1[i]) then
				return false
			end
		else
			for ie=1,#t2 do
				if type(t2[ie])=="table" then
					print('ya')
					if #t2[ie]>0 then
						CompareTables(t1[i],t2[ie])
					end
				else
					
				end
			end
		end
	end
	return true
end

local t1 = {{"a"}}
local t2 = {{"b"}}
print(CompareTables(t1,t2))

updated the original code, fixed it when testing but didn’t copy into the original post. after checking if the type is a table it would compare the values directly afterwards anyway and return false.

2 Likes