热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Lua:检查表是否可以通过ipairs和ipairs从0开始循环

如何解决《Lua:检查表是否可以通过ipairs和ipairs从0开始循环》经验,为你挑选了2个好方法。

我有一个漂亮的小Lua表解析器打印出漂亮的lua代码,我喜欢它...它的工作非常精彩.有一个轻微的障碍...如果我去打印一个具有任何整数键的表或数组,它会使用它来循环pairs(这不会讽刺代码),但我宁愿ipairs在可能的情况下使用它.所以我想知道是否有可能检查一个表(没有实际查看它),如果它可以使用ipairs循环通过它,否则使用对.那么有没有办法开始循环0而不是Lua的默认1?

Lua Table Parser(在谷歌上找到的基本代码,更改它以使其打印更多阵列友好)...

function TableParser(name, object, tabs)
    local function serializeKeyForTable(k)
        if type(k)=="number" then
            return ""
        end
        if string.find(k,"[^A-z_-]") then
            return k
        end
        return k
    end
    local function serializeKey(k)
        if type(k)=="number" then
            if k == 0 then
                return "\t[" .. k .."] = "
            else
                return "\t"
            end
        end
        if string.find(k,"[^A-z_-]") then
            return "\t" .. k .. " = "
        end
        return "\t" .. k .. " = "
    end
    if not tabs then tabs = "" end
    local function serialize(name, object, tabs) -- = {
        local output = tabs .. (name ~= "" and name .. " = " or "") .. "{" .. "\n"
        for k,v in pairs(object) do
            if type(v) == "number" then
                output = output .. tabs .. serializeKey(k) .. v
            elseif type(v) == "string" then
                output = output .. tabs .. serializeKey(k) .. string.format("%q",v)
            elseif type(v) == "table" then
                output = output .. serialize(serializeKeyForTable(k), v, tabs.."\t")
            elseif type(v) == "boolean" then
                output = output .. tabs .. serializeKey(k) .. tostring(v)
            else
                output = output .. tabs .. serializeKey(k) .. "\"" .. tostring(v) .. "\""
            end                     
            if next(object,k) then
                output = output .. ",\n"
            end
        end
        return output .. "\n" .. tabs .. "}"
    end
    return serialize(name, object, tabs)
end

siffiejoe.. 8

所以我想知道是否有可能检查一个表(没有实际查看它),如果它可以使用ipairs循环通过它,否则使用对.

不要检查,只是做!ipairs首先使用并跟踪ipairs迭代器返回的最大键.然后使用pairs再次迭代并忽略之间的所有整数键1和来自的最大键ipairs.

如果你真的想检查是否ipairs会做某事,那么看看1表中的索引(rawget( object, 1 ) ~= nil).如果不迭代表,则无法检查是否ipairs将覆盖表中的所有元素.

那么有没有办法开始循环0而不是Lua的默认1?

ipairs(t)返回三个值:迭代器函数,表t作为状态变量,以及初始索引值0.如果您使用-1初始索引值,ipairs将启动迭代0(迭代器函数在使用索引值之前总是递增1):

t = { 1, 2, 3, [ 0 ] = 0 }
for i,v in ipairs( t ), t, -1 do  -- only use first value returned by ipairs
  print( i, v )
end

但是,请注意Lua 5.2已添加对新元方法的支持,该元__ipairs方法允许您返回用于ipairs迭代的自定义迭代器三元组,并且在这种情况下返回的迭代器函数可能需要不同的状态和初始索引值.

编辑: 要将建议合并到for k,v in pairs(object) do-loop 之前的代码插入中:

local largest = 0
for k,v in ipairs(object) do
    largest = k
    local t = type(v)
    if t == "table" then
        output = output .. tabs .. "\t" .. serialize( "", v, tabs.."\t" )
    elseif t == "string" then
        output = output .. tabs .. "\t" .. string.format("%q", v)
    else
        output = output .. tabs .. "\t" .. tostring(v)
    end
    output = output .. ",\n"
end

并在循环内添加一个额外的if语句来检查数组键:

for k,v in pairs(object) do
   if type(k) ~= "number" or k <1 or k > largest or math.floor(k) ~= k then
       -- if type(v) == "number" then
       -- ...
   end
end

如果将此修改后的TableParser函数应用于下表:

local t = {
  1, 2, 3,
  value = "x",
  tab = {
    "a", "b", field = "y"
  }
}
print( TableParser( "", t ) )

输出是:

{
    1,
    2,
    3,
    tab = {
        "a",
        "b",
        field = "y"
    },
    value = "x"
}

但是正确地进行表序列化是很棘手的.例如,您的实现不会将循环或表作为键处理.有些实现,请参阅Lua Wiki.



1> siffiejoe..:

所以我想知道是否有可能检查一个表(没有实际查看它),如果它可以使用ipairs循环通过它,否则使用对.

不要检查,只是做!ipairs首先使用并跟踪ipairs迭代器返回的最大键.然后使用pairs再次迭代并忽略之间的所有整数键1和来自的最大键ipairs.

如果你真的想检查是否ipairs会做某事,那么看看1表中的索引(rawget( object, 1 ) ~= nil).如果不迭代表,则无法检查是否ipairs将覆盖表中的所有元素.

那么有没有办法开始循环0而不是Lua的默认1?

ipairs(t)返回三个值:迭代器函数,表t作为状态变量,以及初始索引值0.如果您使用-1初始索引值,ipairs将启动迭代0(迭代器函数在使用索引值之前总是递增1):

t = { 1, 2, 3, [ 0 ] = 0 }
for i,v in ipairs( t ), t, -1 do  -- only use first value returned by ipairs
  print( i, v )
end

但是,请注意Lua 5.2已添加对新元方法的支持,该元__ipairs方法允许您返回用于ipairs迭代的自定义迭代器三元组,并且在这种情况下返回的迭代器函数可能需要不同的状态和初始索引值.

编辑: 要将建议合并到for k,v in pairs(object) do-loop 之前的代码插入中:

local largest = 0
for k,v in ipairs(object) do
    largest = k
    local t = type(v)
    if t == "table" then
        output = output .. tabs .. "\t" .. serialize( "", v, tabs.."\t" )
    elseif t == "string" then
        output = output .. tabs .. "\t" .. string.format("%q", v)
    else
        output = output .. tabs .. "\t" .. tostring(v)
    end
    output = output .. ",\n"
end

并在循环内添加一个额外的if语句来检查数组键:

for k,v in pairs(object) do
   if type(k) ~= "number" or k <1 or k > largest or math.floor(k) ~= k then
       -- if type(v) == "number" then
       -- ...
   end
end

如果将此修改后的TableParser函数应用于下表:

local t = {
  1, 2, 3,
  value = "x",
  tab = {
    "a", "b", field = "y"
  }
}
print( TableParser( "", t ) )

输出是:

{
    1,
    2,
    3,
    tab = {
        "a",
        "b",
        field = "y"
    },
    value = "x"
}

但是正确地进行表序列化是很棘手的.例如,您的实现不会将循环或表作为键处理.有些实现,请参阅Lua Wiki.



2> Deduplicator..:

您总是可以使用pairs和迭代表ipairs,无论它是否有意义.

ipairs迭代数组中存在的序列(这意味着从1开始的顺序整数键,直到第一个缺失值),除非用metamethod __ipairs(5.2)覆盖.

pairs迭代所有键值对next(因此以未指定的顺序),除非用metamethod __pairs(5.2)覆盖.

这意味着ipairs通常不会枚举任何键值对pairs将不会显示.

并且无法验证是否ipairs枚举所有键pairs将枚举,但枚举所有内容并手动测试.

BTW:您可以创建自己的迭代器,它首先遍历序列,然后覆盖其他所有内容:

function my_iter(t)
    local k, cap
    return function()
        local v
        if k == nil then k, cap = 0 end
        if not cap then
            k = k + 1
            v = t[k]
            if v ~= nil then return k, v end
            cap, k = k
        end
        repeat k, v = next(k)
        until type(k) ~= "number" or 0 

虽然可能更好的只是排序漂亮的打印键:

function sorted_iter(t)
    local keys, index = {}, 0
    for k in next, t do
        keys[#keys + 1] = k
    end
    table.sort(keys)
    return function()
        index = index + 1
        local k = keys[index]
        return k, t[k]
    end
end


推荐阅读
author-avatar
静候轮回
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有