如何在 Lua 中获取哈希表中的键数?

Posted

技术标签:

【中文标题】如何在 Lua 中获取哈希表中的键数?【英文标题】:How do I get the number of keys in a hash table in Lua? 【发布时间】:2010-10-13 18:28:09 【问题描述】:
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

【问题讨论】:

【参考方案1】:

我尝试了 # 运算符和 table.getn()。我认为 table.getn() 会做你想做的事,但事实证明它返回的值与 # 相同,即 0。字典似乎在必要时插入了 nil 占位符。

遍历键并计算它们似乎是获取字典大小的唯一方法。

【讨论】:

print(table.getn(myTable)) 这打印 0。 # 是 table.getn 的简写,所以你会得到相同的结果 澄清一下,#tbl 将返回表 tbl 的长度 进一步澄清。 #tbl 对条目进行计数,直到找到 nil 键。它仅适用于常规(非稀疏)数组。即你有 tbl[1]、tbl[2] 等,没有删除或零条目。 有点遗憾,table 命名空间中没有类似的方法。【参考方案2】:

The length operator:

表 t 的长度被定义为任意整数索引 n,使得 t[n] 不为 nil 且 t[n+1] 为 nil;此外,如果 t[1] 为 nil,则 n 可以为零。对于从 1 到给定 n 的非 nil 值的常规数组,它的长度正好是 n,它的最后一个值的索引。如果数组有“洞”(即,其他非 nil 值之间的 nil 值),那么 #t 可以是直接在 nil 值之前的任何索引(也就是说,它可以将任何这样的 nil 值视为结束的数组)。

所以获得长度的唯一方法是对其进行迭代。

【讨论】:

【参考方案3】:

除了手动迭代键之外,通过元方法自动跟踪它很简单。考虑到您可能不想跟踪您创建的每个表,您可以编写一个函数,允许您将任何表转换为键可数对象。以下内容并不完美,但我认为它可以说明这一点:

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

Live Working Example

希望这有帮助! :)

【讨论】:

您无法跟踪密钥的移除情况。 当然可以。您只需使用__index__newindex 添加一个间接级别。【参考方案4】:

Lua 将 table 存储为两个独立的部分:一个 hash 部分和一个 array 部分,len 运算符只处理数组部分,意思是 value 由一个 number 值索引,加上下面提到的规则,所以你没有任何计算“哈希”值的选择,您需要使用 pairs() 函数遍历表。

【讨论】:

以上是关于如何在 Lua 中获取哈希表中的键数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在哈希表中均匀分布不同的键?

在 PowerShell 中合并哈希表:如何?

C ++:指针作为哈希表中的键

哈希表中的条目是否可以使用相同的键和相同的值?

为什么Python字典中的键必须是可哈希的

为什么Python字典中的键必须是可哈希的