Bir masa konsola nasıl atılır?


109

İç içe geçmiş tablolar (n-derin) içeren bir tablonun içeriğini görüntülemede sorun yaşıyorum. Bunu sadece bir printifade veya hızlı ve kirli bir şeyle std'ye veya konsola atmak istiyorum ama nasıl olduğunu anlayamıyorum. Bir NSDictionarygdb kullanarak yazdırırken elde edeceğim kaba eşdeğerini arıyorum .

Yanıtlar:


56

Lua Wiki'ye tablo serileştirme ile göz atmaktan çekinmeyin . Bir tablonun konsola nasıl atılacağına dair çeşitli yollar listeler.

Sadece size en uygun olanı seçmelisiniz. Bunu yapmanın birçok yolu var, ancak genellikle Penlight'tan birini kullanıyorum :

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

6
Aptal ve daha da fazla acemi soru: pl.pretty gibi bir uzantıyı nasıl kurabilirim? Katran toplarını açmadan ve bir şeyleri yerleştirmek için HD'mde ideal noktayı bulmadan bir mücevher kurulumu gibi bir şey yapabilseydim güzel olurdu. Hızlı / acısız bir "bu şekilde yap" var mı?
Cliff

1
Dah, son yorumu göndermeden önce ana sayfaya bakmalıydım! Kurulum umduğum kadar hızlı / acısız değil ama çok da kötü değil.
Cliff

ışık, aradığım şeyi aydınlatıyor!
Cliff

7
@Cliff luarocks penlight yüklemek için
vagabond

101

Bu sorunun zaten yanıtlanmış olarak işaretlendiğini biliyorum, ancak kendi kitaplığımı buraya eklememe izin verin. Inspect.lua olarak adlandırılır ve burada bulabilirsiniz:

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

Bu, başka herhangi bir dosyadan talep edebileceğiniz tek bir dosyadır. Herhangi bir Lua değerini insan tarafından okunabilir bir dizeye dönüştüren bir işlev döndürür:

local inspect = require('inspect')

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

Alt tabloları düzgün şekilde girintiler ve "özyinelemeli tabloları" (kendilerine referanslar içeren tablolar) doğru bir şekilde işler, böylece sonsuz döngülere girmez. Değerleri mantıklı bir şekilde sıralar. Ayrıca metatüre edilebilir bilgileri yazdırır.

Saygılarımızla!


Belki kitaplığınızı Lua Wiki'ye eklemelisiniz . Kitaplığınızın, diğer kitaplıkların yapmadığı meta dosyaları da yazdırdığını görüyorum.
Michal Kottman

Mesele şu ki inspect.lua gerçekten "serileştirme" kategorisine uymuyor. Döndürdüğü metin geçerli Lua kodu değil; hata ayıklama / insan okuması için kullanılması gerekiyordu. Sanırım sonuna küçük bir bağlantı falan ekleyebilirim.
kikito

1
Wiki'ye inspect.lua eklendi.
kikito

Lütfen bunu luarocks'a koyun
Hack-R

3
@ Hack-R luarocks'ta:luarocks install inspect
kikito

87

Bunu yararlı buldum. Çünkü özyineleme varsa iç içe tabloları da yazdırabilir. Çıktıdaki en güzel biçimlendirmeyi vermez, ancak bu kadar basit bir işlev için hata ayıklama için yenmek zordur.

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

Örneğin

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))

Aşağıdaki çıktıyı üretir:

Kişiler: {[1] = {["adres"] = 16 Long Street, ["telefon"] = 123456, ["ad"] = Fred,}, [2] = {["adres"] = 16 Long Street , ["telefon"] = 123456, ["ad"] = Wilma,}, [3] = {["adres"] = 17 Long Street, ["telefon"] = 123457, ["ad"] = Barney, },}


1
Harici bir kitaplığa ihtiyaç duymayan bir şeyi paylaşmak için tebrikler.
Julian Knight

Gerçekten büyük masada, fonksiyonunuz
yığın aşımı

21

bunu buldum:

-- 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

buradan https://gist.github.com/ripter/4270799

benim için oldukça iyi çalışıyor ...


19

Gördüğüm çoğu saf lua baskı tablosu işlevi derin özyineleme ile ilgili bir sorun yaşıyor ve çok derine giderken yığın taşmasına neden olma eğiliminde. Yazdığım bu baskı tablosu fonksiyonunda bu sorun yok. Aynı zamanda, birleştirme işlemini işleme biçimi nedeniyle gerçekten büyük tabloları da işleyebilmelidir. Bu işlevi kişisel kullanımımda, yaklaşık bir saniye içinde dosyalamak için 63 bin satır çıktı.

Çıktı aynı zamanda lua sözdizimini de korur ve komut dosyası, yalnızca sayı, boole, dize ve tablo veri türlerinin biçimlendirilmesine izin verecek şekilde değiştirilirse çıktı dosyaya yazarak basit kalıcı depolama için kolayca değiştirilebilir.

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

İşte bir örnek:

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)

Çıktı:

{
    [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'
    }
}

tabişlev aşırı karmaşık. Temelde sadece string.repeat('\t', amt)ama çok daha az performanslıdır.
val diyor Reinstate Monica

6

Daha önce de belirtildiği gibi, yazmalısınız. İşte benim mütevazı versiyonum: (süper basit versiyon)

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

misal:

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

çıktı (Lua 5.0):

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

1
Çok orjinal! Bunu sevdim.
Jack Giffin


2

Bu, tabloları ve kullanıcı verilerini hariç tutmayı destekleyen sürümüm

-- 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

Bu bir örnektir

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

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

Baskılar:

   ### 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 ###

Kökün istisnaları kaldırmadığına dikkat edin


2

JSON olarak biçimlendirin (daha sonra IDE'de "güzelleştirebilirsiniz"):

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

Kullanım:

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"}

BTW, ayrıca birkaç başka çözüm de yazdım: çok hızlı ve özel karakterlerin kaçtığı: https://github.com/vn971/fast_json_encode


Operasyonun özellikle sorduğu şey olmasa da aslında aradığım şey buydu. Böyle basit bir çözüm için teşekkürler. NodeMCU gibi alan kısıtlı Lua ortamlarında kullanımı kolaylaştırır.
Sawtaytoes

1

Korkarım bunu kendin kodlamalısın. Bunu ben yazdım ve senin işine yarayabilir

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

1
Cevabınız için teşekkürler. Bunu denedim ve şunu elde ettim: küresel 'sıralama' (sıfır değeri) arama girişimi
Cliff

Değişim sortiçin table.sort... Bir yapılmış olmalı local sort = table.sortbu alındı kodunda bir yerde.
Michal Kottman

Biraz yaratıcı olmalısın! Kolaylık sağlamak için kitaplık tablo alanından _G'ye kopyalanan bir dizi sembol vardır. sortbir kopyası table.sort, strrepis string.rep, strmatchis string.matchvs. Eğer daha varsa bana haber verin , cevabımı değiştireceğim.
Borodin

Özür dilerim, yapıyı tekrarlama girişimlerim bir yığın taşmasıyla karşılaştığında oldukça derin bir tablo ağına sahibim. (Kelime oyunu yok!) Özyinelememi gevşetmeye ve uygun kuyruk çağrıları kullanmaya çalışırken başımı vuruyordum ama burada yayınladığım noktada hayal kırıklığına uğradım.
Cliff

Son özyinelemeli olmadığından, özyinelemeyi genel olarak böyle bir işlevden kaldıramazsınız. Ya daha büyük bir yığınla oluşturulmuş bir Lua kullanın ya da yineleme yığınını depolamak için bir Lua tablosunu kullanarak aynı algoritmayı uygulayın.
Borodin

1
--~ 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))

Merhaba dostum, bunu saf Lua'da yapan bir siple kod yazdım, bir hatası var (listenin son öğesinden sonra bir koma yaz) ama onu prototip olarak nasıl hızlı bir şekilde yazdım, onu seninkine uyarlamana izin vereceğim ihtiyacı var.


1

Başka bir versiyon ekleniyor. Bu , kullanıcı verilerini de yinelemeye çalışır .

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

1

Bir tablonun içeriğini yazdırmak için kendi işlevimi kullanıyorum, ancak ortamınıza ne kadar iyi çevrildiğinden emin değilim:

---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

-1

Biraz Alundaio kodunu alçakgönüllülükle değiştirdim:

-- 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

sonra:

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))

verir:

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
  }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.