Lua 4" n"表格的属性

时间:2017-07-25 18:57:51

标签: lua lua-table lua-4.0

在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()

2 个答案:

答案 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

https://www.lua.org/manual/4.0/manual.html#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,但是始终使用局部变量是一个好习惯。访问局部变量也比全局访问快。