Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 我如何在结构上深入比较可能包含循环引用的2个lua表,其中表的键本身可能是表?_Algorithm_Lua_Compare_Structural Equality - Fatal编程技术网

Algorithm 我如何在结构上深入比较可能包含循环引用的2个lua表,其中表的键本身可能是表?

Algorithm 我如何在结构上深入比较可能包含循环引用的2个lua表,其中表的键本身可能是表?,algorithm,lua,compare,structural-equality,Algorithm,Lua,Compare,Structural Equality,此问题类似于先前发布的问题 问题是,那里的解决方案对于简单的深度比较非常有效。但是,它不能正确处理循环引用。更具体地说,以下是: function table_eq(table1, table2) local avoid_loops = {} local function recurse(t1, t2) -- compare value types if type(t1) ~= type(t2) then return false end -- B

此问题类似于先前发布的问题

问题是,那里的解决方案对于简单的深度比较非常有效。但是,它不能正确处理循环引用。更具体地说,以下是:

function table_eq(table1, table2)
   local avoid_loops = {}
   local function recurse(t1, t2)
      -- compare value types
      if type(t1) ~= type(t2) then return false end
      -- Base case: compare simple values
      if type(t1) ~= "table" then return t1 == t2 end
      -- Now, on to tables.
      -- First, let's avoid looping forever.
      if avoid_loops[t1] then return avoid_loops[t1] == t2 end
      avoid_loops[t1] = t2
      -- Copy keys from t2
      local t2keys = {}
      local t2tablekeys = {}
      for k, _ in pairs(t2) do
         if type(k) == "table" then table.insert(t2tablekeys, k) end
         t2keys[k] = true
      end
      -- Let's iterate keys from t1
      for k1, v1 in pairs(t1) do
         local v2 = t2[k1]
         if type(k1) == "table" then
            -- if key is a table, we need to find an equivalent one.
            local ok = false
            for i, tk in ipairs(t2tablekeys) do
               if table_eq(k1, tk) and recurse(v1, t2[tk]) then
                  table.remove(t2tablekeys, i)
                  t2keys[tk] = nil
                  ok = true
                  break
               end
            end
            if not ok then return false end
         else
            -- t1 has a key which t2 doesn't have, fail.
            if v2 == nil then return false end
            t2keys[k1] = nil
            if not recurse(v1, v2) then return false end
         end
      end
      -- if t2 has a key which t1 doesn't have, fail.
      if next(t2keys) then return false end
      return true
   end
   return recurse(table1, table2)
end


local t1 = {}

t1[t1]=t1
t1.x = {[t1] = {1, 2, 3}}

local t2 = {}
local t3 = {}

t2[t3]=t2
t3[t2]=t3
t2.x = {[t3] = {1, 2, 3}}
t3.x = {[t2] = {1, 2, 3}}

print(table_eq(t1, t2))
--[[>
lua: deeptest.lua:15: stack overflow
stack traceback:
    deeptest.lua:15: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    ...
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:26: in function <deeptest.lua:3>
    (...tail calls...)
    deeptest.lua:62: in main chunk
    [C]: in ?
--]]
结构上与下表不同:

local t = {}
t[{}] = 1
t["1"] = {}
local t = {}
local t2 = {}
t[t2] = 1
t["1"] = t2
而在“内容平等”中,他们是平等的


测试用例:

local t1 = {}

t1[t1]=t1
t1.x = {[t1] = {1, 2, 3}}

local t2 = {}
local t3 = {}

t2[t3]=t2
t3[t2]=t3
t2.x = {[t3] = {1, 2, 3}}
t3.x = {[t2] = {1, 2, 3}}

assert(table_eq(t1, t2) == false)
assert(table_eq(t2, t3) == true)

local t4 = {}
t4[{}] = 1
t4["1"] = {}

local t5 = {}
local t6 = {}
t5[t6] = 1
t5["1"] = t6

assert(table_eq(t4, t5) == false)

在本例中,通过更改以下内容,可以轻松修复堆栈溢出:

-- if key is a table, we need to find an equivalent one.
        local ok = false
        for i, tk in ipairs(t2tablekeys) do
           if table_eq(k1, tk) and recurse(v1, t2[tk]) then
致:

前两个测试用例返回true,但第三个测试用例失败,因为表作为键比较内容与内容。如果要测试键是否与实际表相同,则需要将其更改为:

-- if key is a table, we need to find an equivalent one.
        local ok = false
        for i, tk in ipairs(t2tablekeys) do
           if k1 == tk and recurse(v1, t2[tk]) then
但请记住,第二个测试用例将失败,因为您希望表作为键来比较内容与内容,而不是实际的表

你的测试案例互相矛盾,你认为“平等”,所以没有真正的答案。 附言


此函数忽略元数据,这也可以与_eq元方法进行比较。因此,无论如何,这仍然不是一个完整的比较。

你能给出你对平等的定义吗?从你的例子中,我不明白什么应该是表eq(t2,t3)的正确答案。也许可以选择将所有对象推到一个表中,然后断言它们都是浅相等的(以消除误报),然后进行深度比较?该解决方案可能仍然存在误报,但很容易固定到当前算法上。@EgorSkriptunoff
table_eq(t2,t3)
应该是。。。未定义。t2和t3指向同一对象的不同部分(即它们相互参照)。只有
table_eq(t1,t2)
(即
table_eq
与完全隔离的表)才是决定性的。仍在尝试理解预期的比较…一个浅显的比较就足以确定两个表具有相同的键值对。似乎你想要某种结构上的比较;包括,也许所有空表都是等效的?@TomBlodget No。空表只有在系统中是相同的引用时才等效于空表。也就是说,给定两个空表t1和t2,
table_eq(t1,t2)
应该是真的,但是
table_eq({a=t1,b=t2},{a=t2,b=t2})
应该是假的,它们并不矛盾。只是你只看“内容”和“实例”。但我要找的实际上不是结构,而是“结构”。Lua表没有任何结构,实际上就是这样。所以这是不可能的。你可以用一些东西来“排序”这些表,并尝试用这种方式进行结构比较。你说Lua表没有结构是什么意思?它们是一组键值对。它们被称为数据结构是有原因的。如果你不想得到帮助,那没关系,别那么聪明。您只能以两种方式比较表,内容或地址。如果您想比较用于创建表的变量名,您应该了解它们是什么。因为你给他们不同的名字,但他们代表的是完全相同的东西。你也可以比较结构,它是内容和地址以一种非常具体的方式混合在一起。在同一个表中,比较地址,但跨表比较内容。正如我所说,请看这里:它显示了单元测试中一些表的结构。
-- if key is a table, we need to find an equivalent one.
        local ok = false
        for i, tk in ipairs(t2tablekeys) do
           if k1 == tk and recurse(v1, t2[tk]) then