(pubblicato anche sulla mailing list Lua)Come posso confrontare in profondità 2 tabelle Lua, che possono avere o meno tabelle come chiavi?
Così ho scritto algoritmi di deep-copy e voglio testarli per vedere se funzionano nel modo in cui li voglio. Mentre ho accesso alla mappa originale-> copia, voglio un algoritmo di confronto approfondito per uso generico che deve essere in grado di confrontare i tasti della tabella (tabelle come chiavi?).
I miei algoritmi di deep-copy sono disponibili qui: https://gist.github.com/SoniEx2/fc5d3614614e4e3fe131 (non è molto organizzato, ma ce ne sono 3, uno usa le chiamate ricorsive, l'altro usa una tabella di todo e l'altro simula uno stack di chiamate (in un modo molto brutto ma compatibile-5,1))
versione ricorsiva:
local function deep(inp,copies)
if type(inp) ~= "table" then
return inp
end
local out = {}
copies = (type(copies) == "table") and copies or {}
copies[inp] = out -- use normal assignment so we use copies' metatable (if any)
for key,value in next,inp do -- skip metatables by using next directly
-- we want a copy of the key and the value
-- if one is not available on the copies table, we have to make one
-- we can't do normal assignment here because metatabled copies tables might set metatables
-- out[copies[key] or deep(key,copies)]=copies[value] or deep(value,copies)
rawset(out,copies[key] or deep(key,copies),copies[value] or deep(value,copies))
end
return out
end
Edit: ho trovato cose come questa, che in realtà non gestiscono le tabelle come chiavi: http://snippets.luacode.org/snippets/Deep_Comparison_of_Two_Values_3 (copia del frammento qui sotto)
function deepcompare(t1,t2,ignore_mt)
local ty1 = type(t1)
local ty2 = type(t2)
if ty1 ~= ty2 then return false end
-- non-table types can be directly compared
if ty1 ~= 'table' and ty2 ~= 'table' then return t1 == t2 end
-- as well as tables which have the metamethod __eq
local mt = getmetatable(t1)
if not ignore_mt and mt and mt.__eq then return t1 == t2 end
for k1,v1 in pairs(t1) do
local v2 = t2[k1]
if v2 == nil or not deepcompare(v1,v2) then return false end
end
for k2,v2 in pairs(t2) do
local v1 = t1[k2]
if v1 == nil or not deepcompare(v1,v2) then return false end
end
return true
end
Anche la serializzazione non è un'opzione, in quanto l'ordine di serializzazione è "casuale".
Qual è la domanda qui esattamente? Quei lavori? Falliscono in certi casi? Inoltre, non sono sicuro di comprendere appieno ciò che vuoi esattamente. Vuoi essere in grado di confrontare due tabelle arbitrarie l'una con l'altra? La difficoltà ci sarà nell'assicurare che tu esaurisca le chiavi nei tavoli su entrambi i lati. –
@EtanReisner Non ho un modo semplice per testare se funzionano, a parte il prettyprinting dell'input e dell'output e quindi il loro confronto manuale.Se avessi un modo automatico per testarlo, (cioè, confrontarlo in profondità) non dovrei passare il mio tempo a controllare manualmente se funziona correttamente ... Sarebbe anche utile per una suite di test ... – SoniEx2
Sei tu? cercando di confrontare le tabelle come chiavi per valore o per contenuto? Per quanto riguarda le funzioni (come chiavi o valori)? Che dire delle funzioni C (uguali)? Che ne pensi di userdata (lo stesso)? –