回答:
テーブルのシリアル化に関するLua Wikiを自由に参照してください。テーブルをコンソールにダンプする方法のいくつかの方法を示します。
あなたはただどれがあなたに最も合うかを選ばなければなりません。それを行うには多くの方法がありますが、私は通常、Penlightの方法を使用することになります。
> t = { a = { b = { c = "Hello world!", 1 }, 2, d = { 3 } } }
> require 'pl.pretty'.dump(t)
{
a = {
d = {
3
},
b = {
c = "Hello world!",
1
},
2
}
}
この質問には既に回答済みのマークが付けられていますが、ここに自分のライブラリを接続します。これはinspect.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
-- }
サブテーブルを適切にインデントし、「再帰テーブル」(それ自体への参照を含むテーブル)を正しく処理するため、無限ループに陥ることはありません。賢明な方法で値をソートします。また、メタテーブル情報も出力します。
よろしく!
luarocks install inspect
これは便利だと思いました。再帰の場合、ネストされたテーブルも印刷できるためです。これは出力で最も美しいフォーマットを提供しませんが、そのような単純な関数の場合、デバッグに勝るものはありません。
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] = {["address"] = 16 Long Street、["phone"] = 123456、["name"] = Fred、}、[2] = {["address"] = 16 Long Street 、["phone"] = 123456、["name"] = Wilma、}、[3] = {["address"] = 17 Long Street、["phone"] = 123457、["name"] =バーニー、 }、}
これが見つかりました:
-- 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
私にはかなりうまくいきます...
私が見たほとんどの純粋なlua印刷テーブル関数には、深い再帰に関する問題があり、深すぎるとスタックオーバーフローが発生する傾向があります。私が書いたこのテーブル印刷関数には、この問題はありません。また、連結の処理方法により、非常に大きなテーブルを処理できる必要があります。私がこの関数を個人的に使用した場合、約1秒で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'
}
}
tab
関数が複雑すぎます。それは基本的には正確ですstring.repeat('\t', amt)
が、パフォーマンスははるかに劣ります。
前述したように、あなたはそれを書かなければなりません。ここに私の謙虚なバージョンがあります:(超基本的なもの)
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"
table.tostring
metehod metaluaは、実際には非常に完了です。ネストされたテーブルを扱い、インデントレベルは変更可能です。... https://github.com/fab13n/metalua/blob/master/src/lib/metalua/table2.luaを参照してください
これは、テーブルとユーザーデータの除外をサポートする私のバージョンです
-- 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 ###
ルートは除外を削除しないことに注意してください
JSONとしてフォーマット(後でIDEで「美化」できます):
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"}
ところで、私は他のいくつかの解決策も書いています:非常に高速な解決策と特殊文字がエスケープする解決策:https : //github.com/vn971/fast_json_encode
自分でコーディングする必要があります。私はこれを書きました、そしてそれはあなたにいくらか役立つかもしれません
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
sort
へtable.sort
...そこはされている必要がありlocal sort = table.sort
、これはから取られたコード内のどこかで。
sort
コピーであるtable.sort
、strrep
あるstring.rep
、strmatch
あるstring.match
などがこれ以上存在する場合、私に教えてください、私は私の答えを変更します。
--~ 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でこれを行う単純なコードを書きました、それはバグがあります(リストの最後の要素の後にコマを書きます)が、プロトタイプとしてそれをすぐに書いたので、あなたに適合させましょうニーズ。
別のバージョンを追加しています。これもユーザーデータを反復しようとします。
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
私は自分の関数を使用してテーブルの内容を印刷しますが、それが環境にどの程度うまく変換されるかはわかりません。
---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
私は少し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
}
}