树形打印lua table表

时间:2023-03-08 17:51:52
树形打印lua table表
为方便调试lua程序,往往想以树的形式打印出一个table,以观其表内数据。以下罗列了三种种关于树形打印lua table的方法;
法一
local print = print
local tconcat = table.concat
local tinsert = table.insert
local srep = string.rep
local type = type
local pairs = pairs
local tostring = tostring
local next = next function print_lua_table (lua_table, indent) if not lua_table or type(lua_table) ~= "table" then
return;
end indent = indent or
for k, v in pairs(lua_table) do
if type(k) == "string" then
k = string.format("%q", k)
end
local szSuffix = ""
if type(v) == "table" then
szSuffix = "{"
end
local szPrefix = string.rep(" ", indent)
formatting = szPrefix.."["..k.."]".." = "..szSuffix
if type(v) == "table" then
print(formatting)
print_lua_table(v, indent + )
print(szPrefix.."},")
else
local szValue = ""
if type(v) == "string" then
szValue = string.format("%q", v)
else
szValue = tostring(v)
end
print(formatting..szValue..",")
end
end
end
  以上是一个树形打印lua table 【原方法的链接】的基本源码,虽是参考云风的方法而来,却 不能够支持表内循环(打印出来的样子还是挺符合 一般人的心里预期的);

法二

譬如一下这个例子: 因为表内引用了自身造成循环引用,所以打印方法也就成了 死循环了;

a = {}
a.a = {
hello = {
alpha = ,
beta = ,
},
world = {
foo = "ooxx",
bar = "haha",
root = a,
},
}
a.b = {
test = a.a
}
a.c = a.a.hello

下面是 云风大神 关于lua table树形打印的源码链接;

local print = print
local tconcat = table.concat
local tinsert = table.insert
local srep = string.rep
local type = type
local pairs = pairs
local tostring = tostring
local next = next function print_r(root)
local cache = { [root] = "." }
local function _dump(t,space,name)
local temp = {}
for k,v in pairs(t) do
local key = tostring(k)
if cache[v] then
tinsert(temp,"+" .. key .. " {" .. cache[v].."}")
elseif type(v) == "table" then
local new_key = name .. "." .. key
cache[v] = new_key
tinsert(temp,"+" .. key .. _dump(v,space .. (next(t,k) and "|" or " " ).. srep(" ",#key),new_key))
else
tinsert(temp,"+" .. key .. " [" .. tostring(v).."]")
end
end
return tconcat(temp,"\n"..space)
end
print(_dump(root, "",""))
end

那么打印出来的效果是这样:

+a+hello+alpha []
| | +beta []
| +world+root {.}
| +bar [haha]
| +foo [ooxx]
+c {.a.hello}
+b+test {.a}

上面的方法,如果摒除去 root = a 这项元素的循环引用,可打印出来的样子是这样的:

["a"] = {
["hello"] = {
["alpha"] = ,
["beta"] = ,
},
["world"] = {
["bar"] = "haha",
["foo"] = "ooxx",
},
},
["c"] = {
["alpha"] = ,
["beta"] = ,
},
["b"] = {
["test"] = {
["hello"] = {
["alpha"] = ,
["beta"] = ,
},
["world"] = {
["bar"] = "haha",
["foo"] = "ooxx",
},
},
},["a"] = {
["hello"] = {
["alpha"] = ,
["beta"] = ,
},
["world"] = {
["bar"] = "haha",
["foo"] = "ooxx",
},
},
["c"] = {
["alpha"] = ,
["beta"] = ,
},
["b"] = {
["test"] = {
["hello"] = {
["alpha"] = ,
["beta"] = ,
},
["world"] = {
["bar"] = "haha",
["foo"] = "ooxx",
},
},
},

法三:

也可以利用lua的序列化将lua表转化为string,再将其给print出来;

-- 序列化tablle表--將表轉化成string
function serialize(obj)
local lua = ""
local t = type(obj)
if t == "number" then
lua = lua .. obj
elseif t == "boolean" then
lua = lua .. tostring(obj)
elseif t == "string" then
lua = lua .. string.format("%q", obj)
elseif t == "table" then
lua = lua .. "{\n"
for k, v in pairs(obj) do
lua = lua .. "[" .. serialize(k) .. "]=" .. serialize(v) .. ",\n"
end
local metatable = getmetatable(obj)
if metatable ~= nil and type(metatable.__index) == "table" then
for k, v in pairs(metatable.__index) do
lua = lua .. "[" .. serialize(k) .. "]=" .. serialize(v) .. ",\n"
end
end
lua = lua .. "}"
elseif t == "nil" then
return nil
else
return "-nil-"
--error("can not serialize a " .. t .. " type.")
end
return lua
end

下面附上 lua的反序列化方法(即 将string[内容是lua table]再转会lua table)

-- 反序列化tablle表--將string轉化成table
function unserialize(lua)
local t = type(lua)
if t == "nil" or lua == "" then
return nil
elseif t == "number" or t == "string" or t == "boolean" then
lua = tostring(lua)
else
error("can not unserialize a " .. t .. " type.")
end
lua = "return " .. lua
local func = loadstring(lua)
if func == nil then
return nil
end
return func()
end