Lua 4 "n" 属性 个表格
Lua 4 "n" property of tables
在 Lua 4 中,许多 table 都有一个 "n" 属性,它跟踪 table 中的项目数。
是否所有 table 都有这个 属性?
可以覆盖吗?
我问,因为我正在尝试开发一个以有效的 Lua 语法递归打印所有 table 元素的例程,并且想知道过滤所有元素是否安全"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()
并非所有 table 都有此 属性。
可以覆盖。
为什么不使用 for 循环遍历 table?或者如果可能,使用 Lua 5.3 ;)
在 Lua 中,这被称为 table for 循环,在现代 Lua 中,它被称为通用 for 循环。
The table for statement traverses all pairs (index,value) of a given
table. It has the following syntax:
stat ::= for name `,' name in exp1 do block end
A for statement like
for index, value in exp do block end
is equivalent to the code:
do
local _t = exp
local index, value = next(t, nil)
while index do
block
index, value = next(t, index)
end
end
Note the following:
_t is an invisible variable. The name is here for explanatory purposes only.
The behavior is undefined if you assign to index inside the block.
The behavior is undefined if you change the table _t during the traversal.
The variables index and value are local to the statement; you cannot use their values after the for ends.
You can use break to exit a for. If you need the value of index or value, assign them to other variables before breaking.
The order that table elements are traversed is undefined, even for numerical indices. If you want to traverse indices in numerical order,
use a numerical for.
参考Lua手册4.4.4
In Lua 4.x in tables,n 只是 table 的一个元素,就像 table 可以包含的任何其他元素一样,但是它不是 table 机制本身的一部分。
因此,它可以被覆盖或删除。
一些函数使用它,如 tinsert() 和其他 table 函数:
local tbl = { n=0 }
tinsert(tbl, 123)
print(tbl.n) --> 1
这非常有用,因为 getn() 函数仅给出 table 的最高数字索引。但是,如果 table 中只有命名元素或混合索引和命名索引,则 getn() 不会反映 table 中元素的真实数量。如果始终使用 table 函数(如 tinsert())插入(或删除)元素,则 n 是 table.
中元素的准确数量
Lua 4.x --> Lua 5.x equivalent:
getn(tbl) #tbl
tinsert(tbl,e) table.insert(tbl,e) or tbl:insert(e)
当然,您仍然可以使用简单的 table 访问在 table 中添加元素。但由于 n 可能非常有用,请尽量保持更新。
tbl["Bla"] = 234
tbl.Bli = 345
tbl.n = tbl.n + 2
如果 n 在 table 中不存在但某处的代码需要它,可以使用 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会给出table中的元素个数,包括n。这里 tbl.n 的结果是 10。
由于最终我们不希望 n 被算作 table 的真实元素(这是),而是只计算其他元素,我们应该将 n 初始化为 -1 然后。
注意 2:这里使用 Lua 4.x 上值运算符 % 是因为 tbl 变量在 foreach 循环的函数中(不在范围内)不可访问。它可以使用 %tbl 到达。但是,upvalue 始终是只读的,因此无法更改 tbl 变量。以下将在函数中产生错误:
%tbl = { } -- change the reference to another table
%tbl = 135 -- change the ref to the table for a number (or a string, ...)
由于 tbl 变量实际上包含对 table 的引用,所引用的 table 可以修改,因此元素 n 可以毫无问题地更改(以及 table 的其他元素=43=]).
%tbl.n = %tbl.n + 1 -- increment the element n of the referenced table
注意 3:可以使用全局变量 tbl,但最好始终使用局部变量。访问局部变量也比全局变量快。
在 Lua 4 中,许多 table 都有一个 "n" 属性,它跟踪 table 中的项目数。
是否所有 table 都有这个 属性? 可以覆盖吗?
我问,因为我正在尝试开发一个以有效的 Lua 语法递归打印所有 table 元素的例程,并且想知道过滤所有元素是否安全"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()
并非所有 table 都有此 属性。 可以覆盖。
为什么不使用 for 循环遍历 table?或者如果可能,使用 Lua 5.3 ;)
在 Lua 中,这被称为 table for 循环,在现代 Lua 中,它被称为通用 for 循环。
The table for statement traverses all pairs (index,value) of a given table. It has the following syntax:
stat ::= for name `,' name in exp1 do block end
A for statement like
for index, value in exp do block end
is equivalent to the code:
do local _t = exp local index, value = next(t, nil) while index do block index, value = next(t, index) end end
Note the following:
_t is an invisible variable. The name is here for explanatory purposes only.
The behavior is undefined if you assign to index inside the block.
The behavior is undefined if you change the table _t during the traversal.
The variables index and value are local to the statement; you cannot use their values after the for ends.
You can use break to exit a for. If you need the value of index or value, assign them to other variables before breaking.
The order that table elements are traversed is undefined, even for numerical indices. If you want to traverse indices in numerical order, use a numerical for.
参考Lua手册4.4.4
In Lua 4.x in tables,n 只是 table 的一个元素,就像 table 可以包含的任何其他元素一样,但是它不是 table 机制本身的一部分。 因此,它可以被覆盖或删除。
一些函数使用它,如 tinsert() 和其他 table 函数:
local tbl = { n=0 }
tinsert(tbl, 123)
print(tbl.n) --> 1
这非常有用,因为 getn() 函数仅给出 table 的最高数字索引。但是,如果 table 中只有命名元素或混合索引和命名索引,则 getn() 不会反映 table 中元素的真实数量。如果始终使用 table 函数(如 tinsert())插入(或删除)元素,则 n 是 table.
中元素的准确数量Lua 4.x --> Lua 5.x equivalent:
getn(tbl) #tbl
tinsert(tbl,e) table.insert(tbl,e) or tbl:insert(e)
当然,您仍然可以使用简单的 table 访问在 table 中添加元素。但由于 n 可能非常有用,请尽量保持更新。
tbl["Bla"] = 234
tbl.Bli = 345
tbl.n = tbl.n + 2
如果 n 在 table 中不存在但某处的代码需要它,可以使用 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会给出table中的元素个数,包括n。这里 tbl.n 的结果是 10。 由于最终我们不希望 n 被算作 table 的真实元素(这是),而是只计算其他元素,我们应该将 n 初始化为 -1 然后。
注意 2:这里使用 Lua 4.x 上值运算符 % 是因为 tbl 变量在 foreach 循环的函数中(不在范围内)不可访问。它可以使用 %tbl 到达。但是,upvalue 始终是只读的,因此无法更改 tbl 变量。以下将在函数中产生错误:
%tbl = { } -- change the reference to another table
%tbl = 135 -- change the ref to the table for a number (or a string, ...)
由于 tbl 变量实际上包含对 table 的引用,所引用的 table 可以修改,因此元素 n 可以毫无问题地更改(以及 table 的其他元素=43=]).
%tbl.n = %tbl.n + 1 -- increment the element n of the referenced table
注意 3:可以使用全局变量 tbl,但最好始终使用局部变量。访问局部变量也比全局变量快。