Как получить количество ключей в хэш-таблице в Lua?
Вопрос
myTable = {}
myTable["foo"] = 12
myTable["bar"] = "blah"
print(#myTable) -- this prints 0
Должен ли я на самом деле перебирать элементы в таблице, чтобы получить количество ключей?
numItems = 0
for k,v in pairs(myTable) do
numItems = numItems + 1
end
print(numItems) -- this prints 2
Решение
Я экспериментировал как с оператором #, так и с table.getn (). Я думал, что table.getn () будет делать то, что вы хотели, но, как оказалось, он возвращает то же значение, что и #, а именно 0. Похоже, словари вставляют ноль заполнителей по мере необходимости. Р>
Цикл по ключам и их подсчет, похоже, единственный способ получить размер словаря.
Другие советы
Длина таблицы t определяется как любой целочисленный индекс n, такой что t [n] не равен nil и t [n + 1] равен nil; более того, если t [1] равно nil, n может быть нулем. Для обычного массива с ненулевыми значениями от 1 до заданного n его длина в точности равна n, индексу его последнего значения. Если в массиве есть & Quot; hole & Quot; (то есть, значения nil между другими значениями, отличными от nil), тогда #t может быть любым из индексов, которые непосредственно предшествуют значению nil (то есть любое такое значение nil может рассматриваться как конец массива). Р>
поэтому единственный способ получить длину - это итерация по ней.
Помимо перебора ключей вручную, его легко отслеживать с помощью метаметодов. Учитывая, что вы, вероятно, не хотите отслеживать каждую созданную вами таблицу, вы можете просто написать функцию, которая позволит вам конвертировать любую таблицу в объект, подсчитываемый ключом. Следующее не идеально, но я думаю, что это проиллюстрирует:
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
Примеры использования этого могут включать:
-- 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
Пример работающей в режиме реального времени
Надеюсь, это помогло! :) Р>
Lua хранит таблицу как две отдельные части: часть хеша и часть массива, оператор len имеет дело только с частью массива, то есть значением, индексированным по числовому значению, плюс с использованием правил, упомянутых ниже, поэтому у вас нет никаких выбор для подсчета " hash " значение, которое необходимо перебрать в таблице с помощью функции pair () .