2009-03-17 25 views
40
myTable = {} 
myTable["foo"] = 12 
myTable["bar"] = "blah" 
print(#myTable) -- this prints 0 

¿Realmente tengo que repetir los elementos en la tabla para obtener el número de claves?¿Cómo obtengo el número de claves en una tabla hash en Lua?

numItems = 0 
for k,v in pairs(myTable) do 
    numItems = numItems + 1 
end 
print(numItems) -- this prints 2 

Respuesta

19

Experimenté con el operador # y table.getn(). Pensé que table.getn() haría lo que querías, pero resulta que devuelve el mismo valor que #, es decir, 0. Parece que los diccionarios insertan marcadores de posición nulos según sea necesario.

Hacer un bucle sobre las teclas y contarlas parece ser la única forma de obtener el tamaño del diccionario.

+0

de impresión (table.getn (myTable)) Esto imprime 0. – Jay

+3

# es la abreviatura de table.getn por lo que obtendrá los mismos resultados –

+0

para aclarar, #tbl volverá la longitud de la tabla TBL –

6

La longitud de una tabla t se define como cualquier índice entero n tal que t [n] no es nulo yt [n + 1] es nulo; además, si t [1] es nil, n puede ser cero. Para una matriz regular, con valores no nulos desde 1 hasta un n dado, su longitud es exactamente esa n, el índice de su último valor. Si la matriz tiene "agujeros" (es decir, valores nulos entre otros valores no nulos), entonces #t puede ser cualquiera de los índices que precede directamente a un valor nulo (es decir, puede considerar cualquier valor nulo como el final de la matriz). entonces la única forma de obtener longitud es iterar sobre ella.

1

Lua almacena la tabla como dos partes separadas: una parte hash y una parte array, el operador len solo se ocupa de la parte array, es decir, valor indexado por un valor numérico, además de las reglas mencionadas a continuación, por lo que no tiene cualquier opción para contar el valor "hash" que necesita para iterar sobre la tabla con la función pairs().

4

Además de recorrer las teclas manualmente, es fácil hacer un seguimiento automático a través de metametodos. Teniendo en cuenta que probablemente no desee realizar un seguimiento de todas las tablas que crea, puede escribir una función que le permita convertir cualquier tabla en un objeto contable de claves. Lo siguiente no es perfecto, pero creo que sería ilustrar este 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 

ejemplos de uso de esta incluirían:

-- 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

Espero que esto ayudó! :)

+0

No puede rastrear la eliminación de claves. – Timothy003

Cuestiones relacionadas