In Lua, due tabelle create separatamente sono considerati "diversi". Ma se crei una tabella una volta, puoi assegnarla a qualsiasi variabile che vuoi, e quando le paragoni, Lua ti dirà che sono uguali. In altre parole:
t = {}
key = { a = "a" }
t[key] = 4
key2 = key
...
t[key2] -- returns 4
Quindi, questo è il modo semplice e pulito di fare quello che vuoi.Memorizza key
da qualche parte, in modo da poter recuperare il 4
indietro usandolo. Anche questo è molto veloce.
Se si in realtà non voglio farlo ... beh, c'è un modo. Ma è piuttosto inefficiente e brutto.
La prima parte sta creando una funzione che confronta due tabelle separate. Dovrebbe restituire true se due tabelle sono "equivalenti" e false se non lo sono. Chiamiamolo equivalente. Dovrebbe funzionare in questo modo:
equivalent({a=1},{a=1}) -- true
equivalent({a=1,b=2}, {a=1}) -- false
equivalent({a={b=1}}, {a={b=2}}) -- false
La funzione deve essere ricorsiva, per gestire tabelle che contengono tavoli stessi. Inoltre, non deve essere ingannato se una delle tabelle "contiene" l'altra, ma ha più elementi. Sono uscito con questa implementazione; probabilmente ce ne sono di migliori là fuori.
local function equivalent(a,b)
if type(a) ~= 'table' then return a == b end
local counta, countb = 0, 0
for k,va in pairs(a) do
if not equivalent(va, b[k]) then return false end
counta = counta + 1
end
for _,_ in pairs(b) do countb = countb + 1 end
return counta == countb
end
Non ho intenzione di spiegare questa funzione qui. Spero sia abbastanza chiaro cosa faccia.
L'altra parte del puzzle consiste nel rendere t
utilizzare la funzione equivalent
quando si confrontano le chiavi. Questo può essere fatto con un'attenta manipolazione misurabile, e con una tabella di "memorizzazione" extra.
Fondamentalmente trasformiamo t
in un impostore. Quando il nostro codice dice di memorizzare un valore sotto una chiave, non lo salva da solo; invece lo dà al tavolo extra (lo chiameremo così store
). Quando il codice richiede t
per un valore, lo cerca in store
, ma utilizzando la funzione equivalent
per ottenerlo.
Questo è il codice: esempio
local function equivalent(a,b)
... -- same code as before
end
local store = {} -- this is the table that stores the values
t = setmetatable({}, {
__newindex = store,
__index = function(tbl, key)
for k,v in pairs(store) do
if equivalent(k,key) then return v end
end
end
})
Usage:
t[{a = 1}] = 4
print(t[{a = 1}]) -- 4
print(t[{a = 1, b = 2}]) -- nil
Grazie per la risposta. La ragione per cui volevo questo era per un compito di PNL. Estrapro le frasi che memorizzo come tabelle lua (ogni token nella frase come un valore mappato a un indice usando table.insert) e voglio contare la frequenza delle frasi. So che ci sono altri modi per fare ciò che voglio (ad esempio concatenare la frase e usare quella stringa concatenata come chiave) ma richiederebbe passaggi di implementazione aggiuntivi e non sarebbe altrettanto pulita. Sono abbastanza sicuro che tu possa fare ciò che voglio in Java e, essendo nuovo di lua, sto cercando di vedere se c'è un analogo – akobre01
Tale funzione di hash è difficile da scrivere perché l'ordine in cui le tabelle sono attraversate dipende da come è stato creato e quindi le tabelle con le stesse voci possono avere attraversamenti diversi. – lhf
Ecco perché ho detto di raccogliere le chiavi in una tabella e ordinarla per garantire un ordine coerente delle chiavi. –