在Lua 4中,许多表都有" n"跟踪表格内项目数量的属性。
所有表都有此属性吗? 它可以被覆盖吗?
我问,因为我正在尝试开发一个例程,以有效的Lua语法递归地打印所有表格的元素,并且想知道过滤所有&#是否安全#&# 34; N"结果中的项目?
感谢。
[编辑]
这是脚本:
-- ThoughtDump v1.4.0
-- Updated: 2017/07/25
-- *****************
-- Created by Thought (http://hw2.tproc.org)
-- Updated by Mikali
-- DESCRIPTION
-- ***********
-- Parses the globals table and __TDPrints its contents to "HW2.log".
-- Can also be used to parse (i.e., pretty-print) generic tables in some cases.
-- Note: functions & variables must actually be declared in order to be parsed.
-- Otherwise, they are ignored.
-- Note: if parsing a table other than the globals table, the __TDPrinted table
-- values may be in a different order than was originally written. Values with
-- numerical indices are moved to the "top" of the table, followed by values
-- with string indices, followed by tables. Functions appear in different
-- locations, depending on whether they are indexed using a number or a string.
-- Note: despite the fact that nil values cannot be stored in tables, they are
-- still handled.
-- Note: even though functions may be referenced within tables, a function will
-- only be parsed correctly if it is indexed using a string that is the same as
-- the name of the function.
__TDOutputString = ""
function __TDParse(name, value, level, verbose, numbers, collapse)
if ((name == "__TDParse") or (name == "__TDSortHash") or (name == "__TDPrint") or (name == "__TDPrintGlobals()") or (name == "__TDOutputString")) then
return
end
local Element = nil
local ValType = type(value)
local NamType = type(name)
local PreLevel = ""
if (collapse == 0) then
for i = 1, level do
PreLevel = PreLevel .. "\t"
end
end
local ComLevel = ""
if (level ~= 0) then
ComLevel = ","
end
if ((ValType == "function") or (ValType == "userdata")) then
if (NamType == "string") then
Element = PreLevel .. name .. " = " .. name .. ComLevel
elseif (numbers == 1) then
Element = PreLevel .. "[" .. name .. "] = " .. name .. ComLevel
else
Element = PreLevel .. name .. ComLevel
end
elseif (ValType == "string") then
if (NamType == "string") then
Element = PreLevel .. name .. " = \"" .. value .. "\"" .. ComLevel
elseif (numbers == 1) then
Element = PreLevel .. "[" .. name .. "] = \"" .. value .. "\"" .. ComLevel
else
Element = PreLevel .. "\"" .. value .. "\"" .. ComLevel
end
elseif (ValType == "number") then
if (NamType == "string") then
Element = PreLevel .. name .. " = " .. value .. ComLevel
elseif (numbers == 1) then
Element = PreLevel .. "[" .. name .. "] = " .. value .. ComLevel
else
Element = PreLevel .. value .. ComLevel
end
elseif (ValType == "table") then
if (NamType == "string") then
Element = PreLevel .. name .. " ="
elseif (numbers == 1) then
Element = PreLevel .. "[" .. name .. "] ="
else
Element = ""
end
elseif (ValType == "nil") then
if (NamType == "string") then
Element = PreLevel .. name .. " = nil" .. ComLevel
elseif (numbers == 1) then
Element = PreLevel .. "[" .. name .. "] = nil" .. ComLevel
else
Element = PreLevel .. "nil" .. ComLevel
end
else
Element = PreLevel .. "-- unknown object type " .. ValType .. " for object " .. name
end
if (verbose == 1) then
Element = Element .. " -- " .. ValType .. ", tag: " .. tag(value)
end
if (((ValType == "table") and (NamType == "number") and (numbers == 0)) or (collapse == 1)) then
__TDPrint(Element, 0)
else
__TDPrint(Element, 1)
end
if (ValType == "table") then
__TDPrint(PreLevel .. "{", collapse == 0)
__TDSortHash(__TDParse, value, level + 1, verbose, numbers, collapse)
__TDPrint(PreLevel .. "}" .. ComLevel, 1)
end
end
function __TDSortHash(func, tabl, level, verbose, numbers, collapse)
local typesarray = {}
local typescount = {}
local keycount = 1
local keyarray = {}
for i, iCount in tabl do
local thistype = type(iCount)
if not (typesarray[thistype]) then
typescount[thistype] = 0
typesarray[thistype] = {}
end
typescount[thistype] = typescount[thistype] + 1
typesarray[thistype][typescount[thistype]] = i
end
sort(typesarray)
for i, iCount in typesarray do
sort(iCount)
for j, jCount in iCount do
keyarray[keycount] = tostring(jCount)
keycount = keycount + 1
end
end
for i, iCount in keyarray do
local tempcount = tonumber(iCount)
if (tempcount) then
iCount = tempcount
end
func(iCount, tabl[iCount], level, verbose, numbers, collapse)
end
end
function __TDPrint(instring, newline)
__TDOutputString = __TDOutputString .. instring
if (newline == 1) then
__TDOutputString = __TDOutputString .. "\n"
end
end
function __TDPrintGlobals()
__TDOutputString = ""
__TDPrint("globals =", 1)
__TDPrint("{", 1)
__TDSortHash(__TDParse, globals(), 1, 0, 0, 0)
__TDPrint("}\n", 1)
local WriteFile = "$test_globals_write.lua"
writeto(WriteFile)
write(__TDOutputString)
writeto()
end
__TDPrintGlobals()
答案 0 :(得分:1)
并非所有表都具有此属性。 它可以被覆盖。
为什么不使用for循环遍历表?或者,如果可能,使用Lua 5.3;)
在Lua中,这被称为表循环,在现代Lua中,它被称为泛循环。
语句表遍历给定的所有对(索引,值) 表。它具有以下语法:
stat ::= for name `,' name in exp1 do block end
像
这样的for语句for index, value in exp do block end
等同于代码:
do local _t = exp local index, value = next(t, nil) while index do block index, value = next(t, index) end end
请注意以下事项:
_t是一个不可见的变量。此处的名称仅供参考。
如果您在块内分配索引,则行为未定义。
- 如果在遍历期间更改表_t,则行为未定义。
变量索引和值是语句的本地值;你不能在结束后使用他们的价值观。
您可以使用break退出for。如果您需要索引或值的值,请在断开之前将它们分配给其他变量。
表格元素的遍历顺序是未定义的,即使对于数字索引也是如此。如果要按数字顺序遍历索引, 使用数字表示。
请参阅Lua手册4.4.4
答案 1 :(得分:1)
在Lua 4.x的表中,n只是表的一个元素,就像表可以包含的任何其他元素一样,但是它不是表机制本身的一部分。 因此,它可以被覆盖或删除。
一些函数使用它,例如tinsert()和其他表函数:
local tbl = { n=0 }
tinsert(tbl, 123)
print(tbl.n) --> 1
这非常有用,因为getn()函数仅给出表的最高编号索引。但是,如果表中只有命名元素,或者只有混合索引或数字索引以及命名索引,则getn()不会反映表中元素的实际数量。如果始终使用诸如tinsert()之类的表函数插入(或删除)元素,则n是表中元素的准确数量。
Lua 4.x --> Lua 5.x equivalent:
getn(tbl) #tbl
tinsert(tbl,e) table.insert(tbl,e) or tbl:insert(e)
当然,您仍然可以使用简单的表访问权限在表中添加元素。但是由于n可能非常有用,因此请尝试使其也保持更新。
tbl["Bla"] = 234
tbl.Bli = 345
tbl.n = tbl.n + 2
如果表中不存在n,但是某个地方的代码需要使用n,则可以使用for循环将其添加:
local tbl = {1,2,3,4,5,6}; tbl.a=11; tbl.b=22; tbl.c=33
local n = 0
for ie, e in tbl do
n = n + 1
end
tbl.n = n
或foreach循环:
local tbl = {1,2,3,4,5,6}; tbl.a=11; tbl.b=22; tbl.c=33
tbl.n = 0
foreach(tbl, function() %tbl.n = %tbl.n + 1 end )
注1:将tbl.n初始化为0将给出表中的元素数,包括n。这里tbl.n的结果是10。 由于最终我们不希望n被计数为表的实际元素(是),而是仅计数其他元素,因此我们应该将n初始化为-1。
注2:这里使用Lua 4.x升值运算符%的原因是,在foreach循环的函数中(不在作用域中)tbl变量不可用。可以使用%tbl来达到。但是,升值始终是只读的,因此无法更改tbl变量。以下内容将在函数中产生错误:
%tbl = { } -- change the reference to another table
%tbl = 135 -- change the ref to the table for a number (or a string, ...)
由于tbl变量实际上包含对表的引用,因此所引用的表可以进行修改,因此可以毫无问题地更改元素n(以及该表的其他元素)。
%tbl.n = %tbl.n + 1 -- increment the element n of the referenced table
注3:可以使用全局变量tbl,但是始终使用局部变量是一个好习惯。访问局部变量也比全局访问快。