Table Comparision and Index Order

I am currently in a situation where I need to compare two tables to make sure they are the same (similar). Each table being compared is shallow (no nested tables). I am using the HTTP service’s json encode function to string compare the two tables but have ran into an issue regarding the index order of said tables. Below is an example of my problem.

In this case

local a = {
	apple = true,
	cat = true
}

local b = {
	apple = true,
	cat = true
}

HttpService:JSONEncode(a) == HttpService:JSONEncode(b) --true

however in this case

local a = {
	apple = true,
	cat = true
}

local b = {
	cat = true,
	apple = true
}

HttpService:JSONEncode(a) == HttpService:JSONEncode(b) --false

Is there any way to “sort” the indices of the tables so they appear similar when string comparing using json encoding? Note that the tables are shallow and do not contain any nested values.

1 Like

This is a great example of the XY problem in Software engineering.

Your task is to compare the tables. You’re overcomplicating your issue by adding the random need for JSON, especially given that the tables are quite simple in nature. You can solve the problem with two loops (which would be likely faster than making 2 JSON strings)

Note: I don’t have access to Studio so my code is untested, but the general concept should work.

local function isEq(t1, t2)
    for key, value in pairs(t1) do
        if t2[key] ~= value then
            return false
        end
    end

    return true
end

local tablesAreEqual = isEq(a, b) and isEq(b, a)
print(tablesAreEqual)

Note: I added and isEq(b, a), because there might be keys in b that don’t exist in a (tables are not the same). If you are sure that both tables have the exact same keys, then this would be unnecessary.


Bonus answer to your actual question:
Put all key-value pairs in an array, and sort that array. Turn that array to JSON.

local function sortKVP(t)
    local result = {}
    for key, value in pairs(t) do
        table.insert(result, { K = key, V = value })
    end
    table.sort(result, function(a,b) return a.K < b.K end)
    return result
end

local newA = sortKVP(a)
local newB = sortKVP(b)

HttpService:JSONEncode(a) == HttpService:JSONEncode(b) --false
HttpService:JSONEncode(newA) == HttpService:JSONEncode(newB) --true

I don’t see why you would do this, though…

2 Likes

Do you know if there is a specific reason why luau handles tables in this way where index order matters?

slight correction

local function isEq(t1, t2)
    for key, value in pairs(t1) do
        if t2[key] ~= value then
            return false
        end
    end
    return true
end
1 Like

It doesn’t. Dictionaries in Lua don’t have any defined order. The Luau implementation iterates from older to newer elements, because there isn’t any specification that says that the iteration should be in alphabetical order. This is true of most popular HashMap implementations as well (e.g. Dictionary in C# and HashMap in Java iirc)

Because cat appears earlier and later in your two code snippets, the order is different, because that’s how Luau sees it. Behind the scenes, there isn’t any sorting going on, just some arbitrary order that can change at any point. “Order” really only exists for arrays (obviously).

Fixed my post, thank you!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.