ropa - lua tutorial
¿Cómo volcar una tabla a la consola? (11)
Tengo problemas para mostrar el contenido de una tabla que contiene tablas anidadas (n-deep). Me gustaría simplemente volcarlo o la consola a través de una declaración de print
o algo rápido y sucio, pero no puedo entender cómo. Estoy buscando el equivalente aproximado que obtendría al imprimir un NSDictionary
usando gdb.
Como se mencionó anteriormente, debes escribirlo. Aquí está mi versión humilde: (super básico)
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
ejemplo:
local mytbl = { [''1'']="a", 2, 3, b="c", t={d=1} }
tprint(mytbl)
salida (Lua 5.0):
table[1] = 2
table[2] = 3
table["1"] = "a"
table["t"]["d"] = 1
table["b"] = "c"
El table.tostring
table.tostring de metalua es en realidad muy completo. Se trata de tablas anidadas, el nivel de sangría es modificable, ... Ver https://github.com/fab13n/metalua/blob/master/src/lib/metalua/table2.lua
Encontré este útil. Porque si la recursión puede imprimir tablas anidadas también.
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
p.ej
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))
Produce el siguiente resultado:
Gente: {[1] = {["dirección"] = 16 Long Street, ["teléfono"] = 123456, ["nombre"] = Fred,}, [2] = {["dirección"] = 16 Long Street , ["teléfono"] = 123456, ["nombre"] = Wilma,}, [3] = {["dirección"] = 17 Long Street, ["teléfono"] = 123457, ["nombre"] = Barney, },}
Esta es mi versión que admite excluir tablas y datos de usuario
-- 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
Esto es un ejemplo
t = {
location = {
x = 10,
y = 20
},
size = {
width = 100000000,
height = 1000,
},
name = "Sidney",
test = {
hi = "lol",
},
anotherone = {
1,
2,
3
}
}
table.print(t, { "test" })
Huellas dactilares:
### 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 ###
Tenga en cuenta que la raíz no elimina exclusiones
Formatee como JSON (puede "embellecer" en IDE más adelante):
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
Uso:
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"}
Por cierto, también escribí varias otras soluciones: una muy rápida y otra con caracteres especiales de escape: https://github.com/vn971/fast_json_encode
La mayoría de las funciones de tabla de impresión lua pura que he visto tienen un problema con la recursión profunda y tienden a causar un desbordamiento de la pila cuando se avanza demasiado. Esta función de la tabla de impresión que he escrito no tiene este problema. También debería ser capaz de manejar tablas realmente grandes debido a la forma en que maneja la concatenación. En mi uso personal de esta función, produjo 63k líneas para archivar en aproximadamente un segundo.
La salida también mantiene la sintaxis de lua y la secuencia de comandos se puede modificar fácilmente para el almacenamiento persistente simple escribiendo el resultado en el archivo si se modifica para permitir que solo se formateen los tipos de datos numéricos, booleanos, de cadena y de tabla.
function print_table(node)
-- to make output beautiful
local function tab(amt)
local str = ""
for i=1,amt do
str = str .. "/t"
end
return str
end
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 .. tab(depth) .. key .. " = "..tostring(v)
elseif (type(v) == "table") then
output_str = output_str .. tab(depth) .. key .. " = {/n"
table.insert(stack,node)
table.insert(stack,v)
cache[node] = cur_index+1
break
else
output_str = output_str .. tab(depth) .. key .. " = ''"..tostring(v).."''"
end
if (cur_index == size) then
output_str = output_str .. "/n" .. tab(depth-1) .. "}"
else
output_str = output_str .. ","
end
else
-- close the table
if (cur_index == size) then
output_str = output_str .. "/n" .. tab(depth-1) .. "}"
end
end
cur_index = cur_index + 1
end
if (size == 0) then
output_str = output_str .. "/n" .. tab(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
Aquí hay un ejemplo:
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)
Salida:
{
[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''
}
}
Sé que esta pregunta ya ha sido marcada como respondida, pero déjame conectar mi propia biblioteca aquí. Se llama inspect.lua, y puedes encontrarlo aquí:
https://github.com/kikito/inspect.lua
Es solo un archivo único que puede requerir de cualquier otro archivo. Devuelve una función que transforma cualquier valor de Lua en una cadena legible por humanos:
local inspect = require(''inspect'')
print(inspect({1,2,3})) -- {1, 2, 3}
print(inspect({a=1,b=2})
-- {
-- a = 1
-- b = 2
-- }
Sangra las subtablas de forma adecuada y maneja las "tablas recursivas" (tablas que contienen referencias a ellas) correctamente, por lo que no entra en bucles infinitos. Ordena los valores de una manera sensata. También imprime información metaestable.
¡Saludos!
Siéntase libre de navegar el Lua Wiki en la serialización de tablas . Enumera varias formas de cómo volcar una tabla en la consola.
Solo tienes que elegir cuál te conviene más. Hay muchas formas de hacerlo, pero generalmente termino usando el de 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
}
}
Tienes que codificarlo tú mismo, me temo. Escribí esto, y puede ser de alguna utilidad para ti
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
encontró esto:
-- 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
desde aquí https://gist.github.com/ripter/4270799
funciona bastante bien para mí ...
--~ 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))
Hola amigo, escribí un código siple que hace esto en Lua puro, tiene un error (escribe un coma después del último elemento de la lista) pero cómo lo escribí rápidamente como prototipo. Lo dejo adaptarlo a tu necesariamente.