Lua: Check if a table can be looped through via ipairs & ipairs starting at 0
我有一个不错的Lua表解析器,它可以打印出看起来很漂亮的Lua代码,我喜欢它...它的工作原理很漂亮。 有一点小问题...如果我要打印具有任何整数键的表或数组,它会使用
Lua Table Parser(在Google上找到的基本代码,对其进行了更改,以使其打印出更友好的数组)...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | 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"") .."{" .."\ " 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 ..",\ " end end return output .."\ " .. tabs .."}" end return serialize(name, object, tabs) end |
So I want to know is it possible to check a table (without physically looking at it) if it can use ipairs to loop through it first else use pairs.
不要检查,只是做!首先使用
如果您确实要检查
Then is there a way to start looping at 0 instead of Lua's default 1?
1 2 3 4 | 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添加了对新元方法
编辑:
要将建议纳入代码中,请在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 ..",\ " end |
并在循环内添加一个附加的
1 2 3 4 5 6 | 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 |
如果将此修改后的
1 2 3 4 5 6 7 8 | local t = { 1, 2, 3, value ="x", tab = { "a","b", field ="y" } } print( TableParser("", t ) ) |
输出为:
1 2 3 4 5 6 7 8 9 10 11 | { 1, 2, 3, tab = { "a", "b", field ="y" }, value ="x" } |
但是正确地进行表序列化非常棘手。例如。您的实现不将循环或表作为键处理。有关某些实现,请参见Lua Wiki。
无论是否有意义,您都可以始终使用
-
ipairs 遍历数组中存在的序列(这意味着从1开始一直到第一个缺失值的连续整数键),除非被元方法__ipairs (5.2)覆盖。 -
除非使用元方法
__pairs (5.2)覆盖,否则pairs 会使用next 遍历所有键值对(因此未指定顺序)。
这意味着
而且没有办法验证
顺便说一句:您可以创建自己的迭代器,该迭代器首先对序列进行迭代,然后对其他所有事物进行迭代:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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 < k and k < cap and math.ceil(k) == k return k, v end end |
尽管可能更好,但对漂亮打印的键进行排序:
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |