请阅读Lua 参考手册:3.4.7 长度运算符
应用于表格的长度运算符返回该表格中的边框。表 t 中的边框是满足以下条件的任意自然数:
(border == 0 or t[border] ~= nil) and t[border + 1] == nil
换句话说,边框是表中存在的任何(自然)索引,后跟不存在的索引(或零,当索引 1 不存在时)。
只有一个边框的表格称为序列。例如,表格 {10, 20, 30, 40, 50} 是一个序列,因为它只有一个边框 (5)。表格 {10, 20, 30, nil, 50} 有两个边界(3 和 5),因此它不是一个序列。(索引 4 处的 nil 称为孔。)表格 {nil, 20, 30, nil, nil, 60, nil} 具有三个边界(0、3 和 6)和三个孔(索引 1、4、和 5),所以它也不是一个序列。表 {} 是一个边界为 0 的序列。请注意,非自然键不会干扰表是否为序列。
当 t 是一个序列时,#t 返回它的唯一边界,这对应于序列长度的直观概念。当 t 不是一个序列时,#t 可以返回它的任何边界。(确切的取决于表的内部表示的细节,而这又取决于表的填充方式及其非数字键的内存地址。)
应用于您的示例:
local t1={}
t1[1]="Foo"
t1[2]="Bar"
t1
只有一个寄宿生 (2),因为t1[2] ~= nil and t1[2+1] == nil
.
t1
只有 1 个边框 ->t1
是一个序列 ->#t1
是t1
.
local t2={}
t2[5]="Foo"
t2[40]="Bar"
t2
有 3 个边界 (0, 5, 40),因为boarder == 0 and t[0+1] == nil
, t[5] ~= nil and t[5+1] == nil
,t[40]~=nil and t[40+1]==nil
t2
有多个边界->#t2
是它的任何一个边界,而不是它的长度。
local t3={}
t3["A"]="Foo"
t3["B"]="Bar"
t3
有 1 个边框 (0),因为border == 0 and t3[0+1] == nil
,没有更多的数字键,所以没有更多的边框。t3
只有一个边框 ->t3
是一个长度为 0 的序列。
local t4={}
t4.A="Foo"
t4.B="Bar"
与t4
ast.name
的语法糖相同t["name"]
。仅适用于有效的 Lua 名称!
t1
是你的例子中唯一的序列,因此唯一的一个#
产生元素的数量。
如果你不确定你是否有一个序列,你应该像这样计算元素:
local n = 0
for _ in pairs(t) do
n = n + 1
end
这是您打印表格边界的方式t
:
function printBorders(t)
local borders = {}
for k in pairs(t) do
if type(k) == "number" and
t[k] ~= nil and t[k+1] == nil then
table.insert(borders, k)
end
end
if t[1] == nil then table.insert(borders, 0) end
table.sort(borders)
print(table.concat(borders, ", "))
end