如何检查两个表(对象)在Lua中是否具有相同的值

Let*_*OMG 14 lua lua-table

我想检查两个表是否在Lua中具有相同的值,但是没有找到方法.

我使用运算符==,它似乎只是检查相同的对象,但不是表中的元素.

如果我有两张桌子,

a={}
b={}
Run Code Online (Sandbox Code Playgroud)

价值a==bfalse.

但如果

a={}
b=a
Run Code Online (Sandbox Code Playgroud)

价值a==btrue.

我想知道是否有办法检查Lua中具有相同元素的两个表.是否有内置功能table.equals()可以检查?

lhf*_*lhf 8

没有用于按内容比较表的内置函数.

你必须自己写.您需要决定是要逐个或深入地按内容比较表.有关一些想法,请参阅https://web.archive.org/web/20131225070434/http://snippets.luacode.org/snippets/Deep_Comparison_of_Two_Values_3.


Dav*_*sky 8

如果你真的想测试简单的表试试这个......

function do_tables_match( a, b )
    return table.concat(a) == table.concat(b)
end
Run Code Online (Sandbox Code Playgroud)

另外,与您的具体示例相比的内容如下...

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
Run Code Online (Sandbox Code Playgroud)


小智 7

我为Rutrus解决方案提供了一些改进.

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
Run Code Online (Sandbox Code Playgroud)

请注意,此解决方案不考虑自引用.你可以使用pequals(下面).当你的代码中有一些技巧时,这很有用.但是不要使用这种方法进行定期检查!它慢了.此外,如果您的对象具有自引用,则应重新分析您的结构.自我引用可能是糟糕架构的标志.

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
Run Code Online (Sandbox Code Playgroud)

您也可以在lua wiki上分析CompareTables.