我有一个漂亮的小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