2009-03-17 18 views

risposta

19

Ho sperimentato sia con l'operatore # che con table.getn(). Pensavo che table.getn() avrebbe fatto ciò che volevi ma come risulta che restituisce lo stesso valore di #, vale a dire 0. Sembra che i dizionari inseriscano nil segnaposto se necessario.

Il looping dei tasti e il loro conteggio sembra l'unico modo per ottenere la dimensione del dizionario.

+0

stampa (table.getn (myTable)) Questa stampa 0. – Jay

+3

# è una scorciatoia per table.getn in modo da otterrete stessi risultati –

+0

Per chiarire, #tbl restituirà la lunghezza della tabella tbl –

6

La lunghezza di una tabella t è definita come qualsiasi indice intero n tale che t [n] non è nil e t [n + 1] è nullo; inoltre, se t [1] è nullo, n può essere zero. Per un array regolare, con valori non nulli da 1 a un dato n, la sua lunghezza è esattamente n, l'indice del suo ultimo valore. Se la matrice ha "buchi" (ovvero valori nulli tra altri valori non nulli), allora #t può essere uno qualsiasi degli indici che precedono direttamente un valore nullo (cioè, può considerare qualsiasi valore nullo come la fine dell'array). quindi l'unico modo per ottenere la lunghezza è iterare su di esso.

1

Lua memorizza la tabella come due parti separate: una parte hash e una parte matrice, l'operatore len gestisce solo la parte dell'array, ovvero il valore indicizzato da un valore numerico, più le regole indicate di seguito, quindi non si dispone qualsiasi scelta per il conteggio del valore "hash" necessario per iterare sul tavolo con la funzione pairs().

4

Oltre a scorrere manualmente i tasti, è semplice tenerne traccia automaticamente tramite metametodi. Considerando che probabilmente non vuoi tenere traccia di ogni tabella che crei, puoi semplicemente scrivere una funzione che ti consenta di convertire qualsiasi tabella in un oggetto numerabile a chiave. Quanto segue non è perfetto, ma penso che sarebbe illustrare il punto:

function CountedTable(x) 
    assert(type(x) == 'table', 'bad parameter #1: must be table') 

    local mt = {} 
    -- `keys` will represent the number of non integral indexes 
    -- `indxs` will represent the number of integral indexes 
    -- `all` will represent the number of both 
    local keys, indxs, all = 0, 0, 0 

    -- Do an initial count of current assets in table. 
    for k, v in pairs(x) do 
    if (type(k) == 'number') and (k == math.floor(k)) then indxs = indxs + 1 
    else keys = keys + 1 end 

    all = all + 1 
    end 

    -- By using `__nexindex`, any time a new key is added, it will automatically be 
    -- tracked. 
    mt.__newindex = function(t, k, v) 
    if (type(k) == 'number') and (k == math.floor(k)) then indxs = indxs + 1 
    else keys = keys + 1 end 

    all = all + 1 
    t[k] = v 
    end 

    -- This allows us to have fields to access these datacounts, but won't count as 
    -- actual keys or indexes. 
    mt.__index = function(t, k) 
    if k == 'keyCount' then return keys 
    elseif k == 'indexCount' then return indxs 
    elseif k == 'totalCount' then return all end 
    end 

    return setmetatable(x, mt) 
end 

Esempi di utilizzo di questo dovrebbe includere:

-- Note `36.35433` would NOT be counted as an integral index. 
local foo = CountedTable { 1, 2, 3, 4, [36.35433] = 36.35433, [54] = 54 } 
local bar = CountedTable { x = 23, y = 43, z = 334, [true] = true } 
local foobar = CountedTable { 1, 2, 3, x = 'x', [true] = true, [64] = 64 } 

print(foo.indexCount) --> 5 
print(bar.keyCount)  --> 4 
print(foobar.totalCount) --> 6 

Live Working Example

Spero che questo ha aiutato! :)

+0

Non è possibile tracciare la rimozione delle chiavi. – Timothy003

Problemi correlati