非数字索引和#符号从不计算?

假设有一个混合索引的表格,比如:

table = {
  foo = 'bar'
  [1] = 'foobar'
}

我的问题是关于通过迭代表格时,# 给出的最后一个未通过间隙分离的索引。

print(#table)

输出结果应为1

table = {
  foo = 'bar',
  lol = 'rofl',
  [1] = 'some',
  [2] = 'thing',
  [3] = 'anything',
  [4] = 'else'
}
print(#table)

应该打印出4

我能否百分之百确定 # 永远不会被非数字索引干扰? 这些索引真的在任何时候被忽略吗?

点赞
用户258523
用户258523

在Lua 5.1中,你可以依赖这个(Yes, you can count on that)。

根据Lua参考手册

长度操作符由一元操作符#表示。字符串的长度是指它的字节数(即当每个字符为一个字节时的字符串长度。)。

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

在Lua 5.2中,__len元方法可用于操作表,这意味着#可以做其他事情。有关示例,请参见@kikito的答案。

2014-10-28 11:44:43
用户882913
用户882913

唯一的方法是遍历表项并对它们进行计数。可以通过使用ipairs迭代表项来增加计数器,然后返回结果。

function tablelength(T)
 local count = 0 
 for _ in pairs(T) do
    count = count + 1 
 end
 return count
end

# 运算符只适用于哈希表类型。

参考:如何在 Lua 表中获取条目数?

2014-10-28 11:47:41
用户312586
用户312586

在 Lua 中,如果一个表的元表有一个 __len 函数,它将控制 # 操作符的输出。可以定义它来考虑非数组键。

local mt = {__len = function(tbl)
  local len = 0
  for _ in pairs(tbl) do len = len + 1 end
  return len
end}

这演示了这个事情:

local t = {1,2,3,4,foo='bar',baz='qux'}

print(#t) -- 4
setmetatable(t, mt)
print(#t) -- 6

如果你 真的 想确保获得“正确”的类似数组的长度,你必须使用 rawlen

print(rawlen(t)) -- 4,即使设置了元表

编辑:注意,在 Lua 5.1 上,__len 不像我说的那样工作。

2014-10-28 14:56:44