¿Cómo obtengo el número de claves en una tabla hash en Lua?
Pregunta
myTable = {}
myTable["foo"] = 12
myTable["bar"] = "blah"
print(#myTable) -- this prints 0
¿Realmente tengo que recorrer los elementos de la tabla para obtener el número de claves?
numItems = 0
for k,v in pairs(myTable) do
numItems = numItems + 1
end
print(numItems) -- this prints 2
Solución
Experimenté con el operador # y table.getn (). Pensé que table.getn () haría lo que quisieras, 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.
Recorrer las teclas y contarlas parece ser la única forma de obtener el tamaño del diccionario.
Otros consejos
La longitud de una tabla t se define como cualquier índice entero n tal que t [n] no es nulo y t [n + 1] es nulo; además, si t [1] es nulo, n puede ser cero. Para una matriz regular, con valores no nulos de 1 a un n dado, su longitud es exactamente ese 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 preceden directamente a un valor nulo (es decir, puede considerar cualquier valor nulo como el final de la matriz).
así que la única forma de obtener longitud es iterar sobre ella.
Además de iterar a través de las teclas manualmente, es sencillo realizar un seguimiento automático a través de metametodos. Teniendo en cuenta que probablemente no desee realizar un seguimiento de cada tabla que haga, simplemente puede escribir una función que le permitirá convertir cualquier tabla en un objeto contable por clave. Lo siguiente no es perfecto, pero creo que ilustraría el 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 esto 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
¡Espero que esto haya ayudado! :)
Lua almacena la tabla como dos partes separadas: una parte hash y una parte de matriz, el operador len solo trata con la parte de matriz, es decir, el valor indexado por un valor numérico, además de usar las reglas mencionadas a continuación, para que no tenga ninguna elección para contar '' hash '' valor que necesita iterar sobre la tabla con la función pares () .