(Zamieszczone również na liście mailingowej Lua)Jak mogę głębiej porównać 2 tabele Lua, które mogą lub nie mają tabel jako kluczy?
Tak więc pisałem algorytmy głębokiego kopiowania i chcę przetestować je, aby sprawdzić, czy działają tak, jak chcę. Chociaż mam dostęp do oryginalnej-> kopii mapy, potrzebuję algorytmu do głębokiego porównania ogólnego zastosowania, który musi być w stanie porównać klucze tabeli (tabele jako klucze?).
Moje algorytmy (kopie) do kopiowania są dostępne tutaj: https://gist.github.com/SoniEx2/fc5d3614614e4e3fe131 (jest niezbyt uporządkowany, ale są 3 z nich, jeden używa wywołań rekursywnych, drugi używa tabeli wywołań, a drugi symuluje stos wywołań (w bardzo brzydki, ale 5,1-kompatybilnym sposób))
wersji rekurencyjne:
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: Znalazłem takie rzeczy, które tak naprawdę nie obsługiwać tabele kluczy: http://snippets.luacode.org/snippets/Deep_Comparison_of_Two_Values_3 (kopia fragmentu poniżej)
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
Serializacja również nie jest opcją, ponieważ kolejność serializacji jest "losowa".
Na czym dokładnie polega pytanie? Czy to działa? Czy w niektórych przypadkach zawodzą? Nie jestem też pewna, czy w pełni rozumiem, czego dokładnie chcesz. Chcesz mieć możliwość porównania dwóch dowolnych tabel ze sobą? Trudność będzie polegała na tym, żebyś wyczerpywał klucze w tabelach po obu stronach. –
@EtanReisner Nie mam łatwego sposobu na sprawdzenie, czy działają, poza udoskonaleniem drukowania danych wejściowych i wyjściowych, a następnie ręcznym ich porównywaniem.Gdybym miał zautomatyzowany sposób testowania, (aka, głęboko to porównać) nie musiałbym spędzać czasu ręcznie sprawdzając, czy działa poprawnie ... Byłby również przydatny dla zestawu testowego ... – SoniEx2
Czy jesteś próbuje porównać tabele jako klucze według wartości lub według zawartości? A co z funkcjami (jako klucze lub wartości)? A co z funkcjami C (tak samo)? Co z danymi użytkownika (takimi samymi)? –