如何将数据表内容输出到控制台?

我在打印包含嵌套表(n 维)内容时遇到了麻烦。我只想通过 print语句或者其他快速而肮脏的方式将它转储到 std out 或者控制台,但是我不知道怎么做。除了通过 gdb 打印 NSDictionary外,还有没有其他方法。

262910 次浏览

恐怕你得自己写代码,这是我写的,可能对你有用

function printtable(table, indent)


indent = indent or 0;


local keys = {};


for k in pairs(table) do
keys[#keys+1] = k;
table.sort(keys, function(a, b)
local ta, tb = type(a), type(b);
if (ta ~= tb) then
return ta < tb;
else
return a < b;
end
end);
end


print(string.rep('  ', indent)..'{');
indent = indent + 1;
for k, v in pairs(table) do


local key = k;
if (type(key) == 'string') then
if not (string.match(key, '^[A-Za-z_][0-9A-Za-z_]*$')) then
key = "['"..key.."']";
end
elseif (type(key) == 'number') then
key = "["..key.."]";
end


if (type(v) == 'table') then
if (next(v)) then
printf("%s%s =", string.rep('  ', indent), tostring(key));
printtable(v, indent);
else
printf("%s%s = {},", string.rep('  ', indent), tostring(key));
end
elseif (type(v) == 'string') then
printf("%s%s = %s,", string.rep('  ', indent), tostring(key), "'"..v.."'");
else
printf("%s%s = %s,", string.rep('  ', indent), tostring(key), tostring(v));
end
end
indent = indent - 1;
print(string.rep('  ', indent)..'}');
end

欢迎浏览 表序列化上的 Lua Wiki。它列出了几种如何将表转储到控制台的方法。

你只需要选择最适合你的。有很多种方法可以做到这一点,但我通常最终使用的是 手电筒中的一种:

> t = { a = { b = { c = "Hello world!", 1 }, 2, d = { 3 } } }
> require 'pl.pretty'.dump(t)
{
a = {
d = {
3
},
b = {
c = "Hello world!",
1
},
2
}
}

我知道这个问题已经被标记为已回答,但是让我在这里插入我自己的库。这叫做“视察 Lua”你可以在这里找到:

Https://github.com/kikito/inspect.lua

它只是一个单一的文件,您可以要求从任何其他文件。它返回一个函数,该函数将任何 Lua 值转换为人类可读的字符串:

local inspect = require('inspect')


print(inspect({1,2,3})) -- {1, 2, 3}
print(inspect({a=1,b=2})
-- {
--   a = 1
--   b = 2
-- }

它正确地缩进子表,并且正确地处理“递归表”(包含对自身的引用的表) ,所以它不会进入无限循环。它以合理的方式对价值进行分类。它还打印元表信息。

问候!

重金属table.tostring方法实际上是非常完整的,它处理的是嵌套的表,缩进级别是可变的,..。 请参见 https://github.com/fab13n/metalua/blob/master/src/lib/metalua/table2.lua

--~ print a table
function printTable(list, i)


local listString = ''
--~ begin of the list so write the {
if not i then
listString = listString .. '{'
end


i = i or 1
local element = list[i]


--~ it may be the end of the list
if not element then
return listString .. '}'
end
--~ if the element is a list too call it recursively
if(type(element) == 'table') then
listString = listString .. printTable(element)
else
listString = listString .. element
end


return listString .. ', ' .. printTable(list, i + 1)


end




local table = {1, 2, 3, 4, 5, {'a', 'b'}, {'G', 'F'}}
print(printTable(table))

嗨,伙计,我写了一个简单的代码,这样做在纯 Lua,它有一个错误(写一个昏迷后,列表的最后一个元素) ,但我如何快速写它作为一个原型,我会让它适应你的需要。

发现了这个:

-- Print contents of `tbl`, with indentation.
-- `indent` sets the initial level of indentation.
function tprint (tbl, indent)
if not indent then indent = 0 end
for k, v in pairs(tbl) do
formatting = string.rep("  ", indent) .. k .. ": "
if type(v) == "table" then
print(formatting)
tprint(v, indent+1)
elseif type(v) == 'boolean' then
print(formatting .. tostring(v))
else
print(formatting .. v)
end
end
end

从这里 Https://gist.github.com/ripter/4270799

我觉得挺好的。

如果需求是“快速和肮脏”

我发现这个很有用。由于递归,它还可以打印嵌套表。它并没有给出输出中最漂亮的格式,但是对于这样一个简单的函数来说,很难在调试方面打败它。

function dump(o)
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
end

例如:。

local people = {
{
name = "Fred",
address = "16 Long Street",
phone = "123456"
},


{
name = "Wilma",
address = "16 Long Street",
phone = "123456"
},


{
name = "Barney",
address = "17 Long Street",
phone = "123457"
}


}


print("People:", dump(people))

产生以下产出:

人们: {[1] = {[“地址”] = 16 Long Street,[“电话”] = 123456,[“ name”] = Fred,} ,[2] = {[“ address”] = 16 Long Street,[“ phone”] = 123456,[“ name”] = Wilma,} ,[3] = {[“ address”] = 17 长街,[“电话”] = 123457,[“名字”] = 巴尼,} ,}

这是我的版本,支持排除表和用户数据

-- Lua Table View by Elertan
table.print = function(t, exclusions)
local nests = 0
if not exclusions then exclusions = {} end
local recurse = function(t, recurse, exclusions)
indent = function()
for i = 1, nests do
io.write("    ")
end
end
local excluded = function(key)
for k,v in pairs(exclusions) do
if v == key then
return true
end
end
return false
end
local isFirst = true
for k,v in pairs(t) do
if isFirst then
indent()
print("|")
isFirst = false
end
if type(v) == "table" and not excluded(k) then
indent()
print("|-> "..k..": "..type(v))
nests = nests + 1
recurse(v, recurse, exclusions)
elseif excluded(k) then
indent()
print("|-> "..k..": "..type(v))
elseif type(v) == "userdata" or type(v) == "function" then
indent()
print("|-> "..k..": "..type(v))
elseif type(v) == "string" then
indent()
print("|-> "..k..": ".."\""..v.."\"")
else
indent()
print("|-> "..k..": "..v)
end
end
nests = nests - 1
end


nests = 0
print("### START TABLE ###")
for k,v in pairs(t) do
print("root")
if type(v) == "table" then
print("|-> "..k..": "..type(v))
nests = nests + 1
recurse(v, recurse, exclusions)
elseif type(v) == "userdata" or type(v) == "function" then
print("|-> "..k..": "..type(v))
elseif type(v) == "string" then
print("|-> "..k..": ".."\""..v.."\"")
else
print("|-> "..k..": "..v)
end
end
print("### END TABLE ###")
end

这是一个例子

t = {
location = {
x = 10,
y = 20
},
size = {
width = 100000000,
height = 1000,
},
name = "Sidney",
test = {
hi = "lol",
},
anotherone = {
1,
2,
3
}
}


table.print(t, { "test" })

印刷品:

   ### START TABLE ###
root
|-> size: table
|
|-> height: 1000
|-> width: 100000000
root
|-> location: table
|
|-> y: 20
|-> x: 10
root
|-> anotherone: table
|
|-> 1: 1
|-> 2: 2
|-> 3: 3
root
|-> test: table
|
|-> hi: "lol"
root
|-> name: "Sidney"
### END TABLE ###

注意,根并没有移除排除

我见过的大多数纯 lua 打印表函数都存在深度递归的问题 并且当进入太深时容易导致堆栈溢出 表函数没有这个问题。由于它处理连接的方式,它还应该能够处理真正大的表。在我个人使用这个函数时,它在大约一秒钟内输出63k 行文件。

输出还保留了 lua 语法,并且脚本可以很容易地修改 通过将输出写入文件(如果修改为允许)来实现简单的持久存储 只有数字、布尔值、字符串和表格数据类型需要格式化。

function print_table(node)
local cache, stack, output = {},{},{}
local depth = 1
local output_str = "{\n"


while true do
local size = 0
for k,v in pairs(node) do
size = size + 1
end


local cur_index = 1
for k,v in pairs(node) do
if (cache[node] == nil) or (cur_index >= cache[node]) then


if (string.find(output_str,"}",output_str:len())) then
output_str = output_str .. ",\n"
elseif not (string.find(output_str,"\n",output_str:len())) then
output_str = output_str .. "\n"
end


-- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
table.insert(output,output_str)
output_str = ""


local key
if (type(k) == "number" or type(k) == "boolean") then
key = "["..tostring(k).."]"
else
key = "['"..tostring(k).."']"
end


if (type(v) == "number" or type(v) == "boolean") then
output_str = output_str .. string.rep('\t',depth) .. key .. " = "..tostring(v)
elseif (type(v) == "table") then
output_str = output_str .. string.rep('\t',depth) .. key .. " = {\n"
table.insert(stack,node)
table.insert(stack,v)
cache[node] = cur_index+1
break
else
output_str = output_str .. string.rep('\t',depth) .. key .. " = '"..tostring(v).."'"
end


if (cur_index == size) then
output_str = output_str .. "\n" .. string.rep('\t',depth-1) .. "}"
else
output_str = output_str .. ","
end
else
-- close the table
if (cur_index == size) then
output_str = output_str .. "\n" .. string.rep('\t',depth-1) .. "}"
end
end


cur_index = cur_index + 1
end


if (size == 0) then
output_str = output_str .. "\n" .. string.rep('\t',depth-1) .. "}"
end


if (#stack > 0) then
node = stack[#stack]
stack[#stack] = nil
depth = cache[node] == nil and depth + 1 or depth - 1
else
break
end
end


-- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
table.insert(output,output_str)
output_str = table.concat(output)


print(output_str)
end

这里有一个例子:

local t = {
["abe"] = {1,2,3,4,5},
"string1",
50,
["depth1"] = { ["depth2"] = { ["depth3"] = { ["depth4"] = { ["depth5"] = { ["depth6"] = { ["depth7"]= { ["depth8"] = { ["depth9"] = { ["depth10"] = {1000}, 900}, 800},700},600},500}, 400 }, 300}, 200}, 100},
["ted"] = {true,false,"some text"},
"string2",
[function() return end] = function() return end,
75
}


print_table(t)

产出:

{
[1] = 'string1',
[2] = 50,
[3] = 'string2',
[4] = 75,
['abe'] = {
[1] = 1,
[2] = 2,
[3] = 3,
[4] = 4,
[5] = 5
},
['function: 06472B70'] = 'function: 06472A98',
['depth1'] = {
[1] = 100,
['depth2'] = {
[1] = 200,
['depth3'] = {
[1] = 300,
['depth4'] = {
[1] = 400,
['depth5'] = {
[1] = 500,
['depth6'] = {
[1] = 600,
['depth7'] = {
[1] = 700,
['depth8'] = {
[1] = 800,
['depth9'] = {
[1] = 900,
['depth10'] = {
[1] = 1000
}
}
}
}
}
}
}
}
}
},
['ted'] = {
[1] = true,
[2] = false,
[3] = 'some text'
}
}

正如前面提到的,您必须编写它。 以下是我的拙劣版本: (超基本版)

function tprint (t, s)
for k, v in pairs(t) do
local kfmt = '["' .. tostring(k) ..'"]'
if type(k) ~= 'string' then
kfmt = '[' .. k .. ']'
end
local vfmt = '"'.. tostring(v) ..'"'
if type(v) == 'table' then
tprint(v, (s or '')..kfmt)
else
if type(v) ~= 'string' then
vfmt = tostring(v)
end
print(type(t)..(s or '')..kfmt..' = '..vfmt)
end
end
end

例如:

local mytbl = { ['1']="a", 2, 3, b="c", t={d=1} }
tprint(mytbl)

输出(Lua 5.0) :

table[1] = 2
table[2] = 3
table["1"] = "a"
table["t"]["d"] = 1
table["b"] = "c"

有两个解决方案,我想提到: 一个快速和肮脏的一个,另一个正确地逃脱所有的键和值,但是更大

简单快捷的解决方案(仅用于“安全”输入) :

local function format_any_value(obj, buffer)
local _type = type(obj)
if _type == "table" then
buffer[#buffer + 1] = '{"'
for key, value in next, obj, nil do
buffer[#buffer + 1] = tostring(key) .. '":'
format_any_value(value, buffer)
buffer[#buffer + 1] = ',"'
end
buffer[#buffer] = '}' -- note the overwrite
elseif _type == "string" then
buffer[#buffer + 1] = '"' .. obj .. '"'
elseif _type == "boolean" or _type == "number" then
buffer[#buffer + 1] = tostring(obj)
else
buffer[#buffer + 1] = '"???' .. _type .. '???"'
end
end

用法:

local function format_as_json(obj)
if obj == nil then return "null" else
local buffer = {}
format_any_value(obj, buffer)
return table.concat(buffer)
end
end


local function print_as_json(obj)
print(_format_as_json(obj))
end


print_as_json {1, 2, 3}
print_as_json(nil)
print_as_json("string")
print_as_json {[1] = 1, [2] = 2, three = { { true } }, four = "four"}

键/值转义的正确解决方案

我用纯 Lua 为这个特定用例编写的小型库: https://github.com/vn971/fast_json_encode

或者特别是这个包含格式化程序和打印机的1文件: https://github.com/vn971/fast_json_encode/blob/master/json_format.lua

我使用自己的函数来打印表中的内容,但不确定它能否很好地转换到您的环境中:

---A helper function to print a table's contents.
---@param tbl table @The table to print.
---@param depth number @The depth of sub-tables to traverse through and print.
---@param n number @Do NOT manually set this. This controls formatting through recursion.
function PrintTable(tbl, depth, n)
n = n or 0;
depth = depth or 5;


if (depth == 0) then
print(string.rep(' ', n).."...");
return;
end


if (n == 0) then
print(" ");
end


for key, value in pairs(tbl) do
if (key and type(key) == "number" or type(key) == "string") then
key = string.format("[\"%s\"]", key);


if (type(value) == "table") then
if (next(value)) then
print(string.rep(' ', n)..key.." = {");
PrintTable(value, depth - 1, n + 4);
print(string.rep(' ', n).."},");
else
print(string.rep(' ', n)..key.." = {},");
end
else
if (type(value) == "string") then
value = string.format("\"%s\"", value);
else
value = tostring(value);
end


print(string.rep(' ', n)..key.." = "..value..",");
end
end
end


if (n == 0) then
print(" ");
end
end

添加另一个版本。这个 尝试也可以遍历用户数据。

function inspect(o,indent)
if indent == nil then indent = 0 end
local indent_str = string.rep("    ", indent)
local output_it = function(str)
print(indent_str..str)
end


local length = 0


local fu = function(k, v)
length = length + 1
if type(v) == "userdata" or type(v) == 'table' then
output_it(indent_str.."["..k.."]")
inspect(v, indent+1)
else
output_it(indent_str.."["..k.."] "..tostring(v))
end
end


local loop_pairs = function()
for k,v in pairs(o) do fu(k,v) end
end


local loop_metatable_pairs = function()
for k,v in pairs(getmetatable(o)) do fu(k,v) end
end


if not pcall(loop_pairs) and not pcall(loop_metatable_pairs) then
output_it(indent_str.."[[??]]")
else
if length == 0 then
output_it(indent_str.."{}")
end
end
end

我谦卑地修改了一点 Alundaio 代码:

-- by Alundaio
-- KK modified 11/28/2019


function dump_table_to_string(node, tree, indentation)
local cache, stack, output = {},{},{}
local depth = 1




if type(node) ~= "table" then
return "only table type is supported, got " .. type(node)
end


if nil == indentation then indentation = 1 end


local NEW_LINE = "\n"
local TAB_CHAR = " "


if nil == tree then
NEW_LINE = "\n"
elseif not tree then
NEW_LINE = ""
TAB_CHAR = ""
end


local output_str = "{" .. NEW_LINE


while true do
local size = 0
for k,v in pairs(node) do
size = size + 1
end


local cur_index = 1
for k,v in pairs(node) do
if (cache[node] == nil) or (cur_index >= cache[node]) then


if (string.find(output_str,"}",output_str:len())) then
output_str = output_str .. "," .. NEW_LINE
elseif not (string.find(output_str,NEW_LINE,output_str:len())) then
output_str = output_str .. NEW_LINE
end


-- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
table.insert(output,output_str)
output_str = ""


local key
if (type(k) == "number" or type(k) == "boolean") then
key = "["..tostring(k).."]"
else
key = "['"..tostring(k).."']"
end


if (type(v) == "number" or type(v) == "boolean") then
output_str = output_str .. string.rep(TAB_CHAR,depth*indentation) .. key .. " = "..tostring(v)
elseif (type(v) == "table") then
output_str = output_str .. string.rep(TAB_CHAR,depth*indentation) .. key .. " = {" .. NEW_LINE
table.insert(stack,node)
table.insert(stack,v)
cache[node] = cur_index+1
break
else
output_str = output_str .. string.rep(TAB_CHAR,depth*indentation) .. key .. " = '"..tostring(v).."'"
end


if (cur_index == size) then
output_str = output_str .. NEW_LINE .. string.rep(TAB_CHAR,(depth-1)*indentation) .. "}"
else
output_str = output_str .. ","
end
else
-- close the table
if (cur_index == size) then
output_str = output_str .. NEW_LINE .. string.rep(TAB_CHAR,(depth-1)*indentation) .. "}"
end
end


cur_index = cur_index + 1
end


if (size == 0) then
output_str = output_str .. NEW_LINE .. string.rep(TAB_CHAR,(depth-1)*indentation) .. "}"
end


if (#stack > 0) then
node = stack[#stack]
stack[#stack] = nil
depth = cache[node] == nil and depth + 1 or depth - 1
else
break
end
end


-- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
table.insert(output,output_str)
output_str = table.concat(output)


return output_str


end

然后:

print(dump_table_to_string("AA", true,3))


print(dump_table_to_string({"AA","BB"}, true,3))


print(dump_table_to_string({"AA","BB"}))


print(dump_table_to_string({"AA","BB"},false))


print(dump_table_to_string({"AA","BB",{22,33}},true,2))

提供:

only table type is supported, got string


{
[1] = 'AA',
[2] = 'BB'
}


{
[1] = 'AA',
[2] = 'BB'
}


{[1] = 'AA',[2] = 'BB'}


{
[1] = 'AA',
[2] = 'BB',
[3] = {
[1] = 22,
[2] = 33
}
}


最简单的方法,包括循环引用处理等等:

function dump(t, indent, done)
done = done or {}
indent = indent or 0


done[t] = true


for key, value in pairs(t) do
print(string.rep("\t", indent))


if type(value) == "table" and not done[value] then
done[value] = true
print(key, ":\n")


dump(value, indent + 2, done)
done[value] = nil
else
print(key, "\t=\t", value, "\n")
end
end
end

在 lua 中转储表的简单示例

我建议使用 毒蛇 Lua

local function parser(value, indent, subcategory)
local indent = indent or 2
local response = '(\n'
local subcategory = type(subcategory) == 'number' and subcategory or indent
for key, value in pairs(value) do
if type(value) == 'table' then
value = parser(value, indent, subcategory + indent)


elseif type(value) == 'string' then
value = '\''.. value .. '\''


elseif type(value) ~= 'number' then
value = tostring(value)
end


if type(tonumber(key)) == 'number' then
key = '[' .. key .. ']'
elseif not key:match('^([A-Za-z_][A-Za-z0-9_]*)$') then
key = '[\'' .. key .. '\']'
end
response = response .. string.rep(' ', subcategory) .. key .. ' = ' .. value .. ',\n'
end
return response .. string.rep(' ', subcategory - indent) .. ')'


end

例子

response = parser{1,2,3, {ok = 10, {}}}
print(response)

结果

(
[1] = 1,
[2] = 2,
[3] = 3,
[4] = (
[1] = (),
ok = 10
)
)

现在函数 打印可以打印(平面)表!

oprint = print -- origin print
print = function (...)
if type(...) == "table" then
local str = ''
local amount = 0
for i,v in pairs(...) do
amount=amount+1
local pre = type(i) == "string" and i.."=" or ""
str = str .. pre..tostring(v) .. "\t"
end
oprint('#'..amount..':', str)
else
oprint(...)
end
end

例如:

print ({x=7, y=9, w=11, h="height", 7, 8, 9})

印刷品:

# 7:789 y = 9 x = 7 h = 身高 w = 11

同样,它也可以是新的函数 Tostring:

otostring = tostring -- origin tostring
tostring = function (...)
if type(...) == "table" then
local str = '{'
for i,v in pairs(...) do
local pre = type(i) == "string" and i.."=" or ""
str = str .. pre..tostring(v) .. ", "
end
str = str:sub(1, -3)
return str..'}'
else
return otostring(...)
end
end

转换为 json 然后打印。

    local json = require('cjson')
json_string = json.encode(this_table)
print (json_string)

这个版本可以打印带标识的表格。可以扩展为递归工作。

function printtable(table, indent)
print(tostring(table) .. '\n')
for index, value in pairs(table) do
print('    ' .. tostring(index) .. ' : ' .. tostring(value) .. '\n')
end
end

这里是 我的小宝贝:

--- Dump value of a variable in a formatted string
--
--- @param o    table       Dumpable object
--- @param tbs  string|nil  Tabulation string, '  ' by default
--- @param tb   number|nil  Initial tabulation level, 0 by default
--- @return     string
local function dump(o, tbs, tb)
tb = tb or 0
tbs = tbs or '  '
if type(o) == 'table' then
local s = '{'
if (next(o)) then s = s .. '\n' else return s .. '}' end
tb = tb + 1
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"' .. k .. '"' end
s = s .. tbs:rep(tb) .. '[' .. k .. '] = ' .. dump(v, tbs, tb)
s = s .. ',\n'
end
tb = tb - 1
return s .. tbs:rep(tb) .. '}'
else
return tostring(o)
end
end