2009-08-09 17 views
96

Qual è il modo più efficiente per determinare se una tabella è vuota (ovvero, al momento non contiene né valori di stile di matrice né valori di stile di dettatura)? ciIl modo più efficace per determinare se una tabella Lua è vuota (non contiene voci)?

if not next(myTable) then 
    -- Table is empty 
end 

è un modo più efficiente:

Attualmente, sto usando next()?

Nota: L'operatore # non basta qui, in quanto opera solo sui valori matrice stile nella tabella - così #{test=2} è indistinguibile da #{} perché entrambi ritorno 0. Si noti inoltre che il controllo se la variabile tabella è nil fa non è sufficiente in quanto non sto cercando valori nulli, ma piuttosto tabelle con 0 voci (ovvero {}).

risposta

118

Il codice è efficiente ma sbagliato. (Considerare {[false]=0}.) Il codice corretto è

if next(myTable) == nil then 
    -- myTable is empty 
end 

Per la massima efficienza si desidera associare next a una variabile locale, ad esempio,

... 
local next = next 
... 
... if next(...) ... 
+1

Buon punto sulla correttezza tecnica; nei casi particolari in cui ho utilizzato il codice originale, 'false' non sarebbe una chiave prevista, quindi il' if not' funzionava bene, ma probabilmente userò il paragone con 'nil' invece in futuro , proprio come una buona abitudine. E sì, ho impegnato funzioni comuni di utilità per le vars locali per la velocità. Grazie per l'input però. – Amber

+1

Trovo difficile concordare con l'errore quando il codice funziona come previsto –

+3

Perché guadagniamo velocità facendo 'local next'? – Moberg

1

Una possibilità sarebbe quella di contare il numero di elementi, utilizzando la chiave "newindex" che è possibile calcolare. Quando si assegna qualcosa non nil, incrementare il contatore (il contatore potrebbe vivere anche nella metatable) e quando si assegna nil, decrementare il contatore.

Test per tavolo vuoto potrebbe essere quella di verificare il contatore con 0.

Ecco un puntatore a metatable documentation

mi piace la vostra soluzione, però, e onestamente non può supporre che la mia soluzione è più veloce complessiva .

+5

La domanda iniziale non è di contare solo voci "matrice". – lhf

+3

Il suggerimento di 0x6 non è specifico per le voci in stile array (newindex funziona sia per indici numerici che non numerici). Tuttavia, il problema principale sarebbe rilevare quando viene assegnato 'nil', poiché __newindex non si attiva se la chiave esiste già nella tabella. – Amber

+3

Perché questo trucco funzioni, il metatable dovrebbe implementare sia '__index' che' __newindex', memorizzando i dati effettivi in ​​una tabella shadow e mantenendo vuota la tabella reale in modo da invocare '__index'. Pensando ad alta voce, sospetto che il costo sollevato di ogni singola ricerca non possa valerne la pena. – RBerteig

0

Questo è probabilmente quello che si voleva:

function table.empty (self) 
    for _, _ in pairs(self) do 
     return false 
    end 
    return true 
end 

a = { } 
print(table.empty(a)) 
a["hi"] = 2 
print(table.empty(a)) 
a["hi"] = nil 
print(table.empty(a)) 

uscita:

true 
false 
true 
+8

'next()' è più efficiente (e più conciso) del loop su 'pairs()'. – Amber

+7

In effetti, il ciclo su 'pairs()' * è * essenzialmente usando solo la tecnica 'next()', ma con un sovraccarico maggiore. – dubiousjim

+7

Inoltre, non è consigliabile scrivere nella libreria 'tabella' standard. –

-1

So che questo è vecchio, e potrei fraintendermi in qualche modo, ma vuoi solo che il tavolo sia vuoto, cioè, a meno che tu stia solo verificando se lo è e in realtà non lo vuoi o non ne hai bisogno per essere vuoto, puoi cancellarlo semplicemente ricreandolo, a meno che non mi sbagli. questo può essere fatto con la seguente sintassi.

yourtablename = {} -- this seems to work for me when I need to clear a table. 
+4

Questa non è la domanda. –

-4

Provare a utilizzare #. Restituisce tutte le istanze presenti in una tabella. Se non ci sono casi in una tabella, poi ritorna 0

if #myTable==0 then 
print('There is no instance in this table') 
end 
+1

Il richiedente dice che '#' non sarà sufficiente qui, e fornisce i motivi per cui; potresti spiegare perché questo aggira queste ragioni? – MathSquared

+0

beh ... non lo so.Io sono nuovo in questo modo l'unico modo che conosco è usare # – arthurgps2

Problemi correlati