Как получить количество ключей в хэш-таблице в 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

person Jay    schedule 17.03.2009    source источник


Ответы (4)


Я экспериментировал как с оператором #, так и с table.getn(). Я думал, что table.getn() сделает то, что вы хотели, но, как оказалось, он возвращает то же значение, что и #, а именно 0. Похоже, что словари вставляют нулевые заполнители по мере необходимости.

Перебор ключей и их подсчет кажется единственным способом получить размер словаря.

person Aaron Saarela    schedule 17.03.2009
comment
print(table.getn(myTable)) Это печатает 0. - person Jay; 17.03.2009
comment
# является сокращением для table.getn, поэтому вы получите те же результаты. - person serioys sam; 17.03.2009
comment
Чтобы уточнить, #tbl вернет длину таблицы tbl. - person Daniel Morris; 06.06.2011
comment
Для дальнейшего уточнения. #tbl считает записи, пока не найдет нулевой ключ. Он работает только для обычных (не разреженных) массивов. то есть, где у вас есть tbl[1], tbl[2] и т. д. без удаленных или нулевых записей. - person James Anderson; 22.06.2011
comment
Немного жаль, что в пространстве имен table нет такого метода. - person polemon; 08.12.2012

Оператор длины:

Длина таблицы t определяется как любой целочисленный индекс n, такой что t[n] не равен нулю и t[n+1] равен нулю; более того, если t[1] равно нулю, n может быть равно нулю. Для обычного массива с ненулевыми значениями от 1 до заданного n его длина точно равна n, индексу его последнего значения. Если в массиве есть «дыры» (то есть нулевые значения между другими ненулевыми значениями), то #t может быть любым индексом, который непосредственно предшествует нулевому значению (то есть он может рассматривать любое такое нулевое значение как конец). массива).

поэтому единственный способ получить длину - это перебрать ее.

person serioys sam    schedule 17.03.2009

Помимо перебора ключей вручную, легко автоматически отслеживать их с помощью метаметодов. Учитывая, что вы, вероятно, не хотите отслеживать каждую созданную вами таблицу, вы можете просто написать функцию, которая позволит вам преобразовать любую таблицу в объект со счетом ключей. Следующее не идеально, но я думаю, что это проиллюстрирует суть:

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

Живой рабочий пример

Надеюсь, это помогло! :)

person Miguel    schedule 03.11.2013
comment
Вы не можете отследить удаление ключей. - person Timothy003; 23.03.2014
comment
Что вы можете. Вам просто нужно добавить уровень косвенности, используя __index и __newindex. - person Qix - MONICA WAS MISTREATED; 01.09.2020

Lua хранит таблицу как две отдельные части: хеш-часть и часть массива, оператор len имеет дело только с частью массива, что означает значение, индексированное числовым значением, плюс использование правил, упомянутых ниже, поэтому у вас нет выбора для подсчета значение "хеш", которое вам нужно перебрать по таблице с помощью функции pairs().

person Faylixe    schedule 16.02.2012