2012-02-06 119 views
61

我無法顯示包含嵌套表(n-deep)的表的內容。我想通過print聲明或者快速而骯髒的東西將它轉儲到標準輸出或控制檯,但我無法弄清楚。我正在尋找使用gdb打印NSDictionary時得到的粗略等價物。如何將錶轉儲到控制檯?

回答

33

隨意瀏覽Lua Wiki on table serialization。它列出瞭如何將錶轉儲到控制檯的幾種方法。

你只需要選擇最適合你的那一種。有很多方法可以做到這一點,但我通常最終會使用從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 
    } 
} 
+3

啞巴,甚至更多新手問題:我如何去安裝像pl.pretty這樣的擴展?如果我可以做一些像寶石一樣的安裝而不需要展開焦油球並找到我的高清位置上的理想位置,那就太好了。有沒有快速/無痛的「這樣做」? – Cliff 2012-02-06 22:53:34

+0

Dah,我應該在發佈最後一條評論前查看主頁!安裝並不像我希望的那樣快速/無痛,但也不是太糟糕。 – Cliff 2012-02-06 22:55:35

+0

penlight照亮我尋找的東西! – Cliff 2012-02-06 23:35:16

1

你必須自己編碼,恐怕。我寫了這一點,這可能是一些使用到你

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

感謝您的回覆。我嘗試了這一點,我得到:嘗試調用全局「排序」(一個零值) – Cliff 2012-02-06 22:21:56

+0

將'sort'更改爲'table.sort' ...代碼中某處存在'local sort = table.sort'這是從哪裏拿走的。 – 2012-02-06 22:26:08

+0

你必須有點想象力!爲了方便,有許多從庫表空間複製到_G的符號。 'sort'是'table.sort'的副本,'strrep'是'string.rep','strmatch'是'string.match'等。讓我知道是否還有更多,我會改變我的答案。 – Borodin 2012-02-06 22:27:25

66

我知道這個問題已經被標記爲回答,但讓我在這裏插入我自己的圖書館。這就是所謂的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 
-- } 

它正確地縮進子表,並正確處理「遞歸表」(包含自己的參考表),所以它不會進入無限循環。它以合理的方式分類價值。它還打印metatable信息。

問候!

+0

也許您應該將您的庫添加到[Lua Wiki](http://lua-users.org/wiki/TableSerialization)。我看到你的圖書館還打印metatables,其他圖書館沒有。 – 2012-02-07 09:12:31

+0

事情是,inspect.lua並不真正適合「序列化」類別。它返回的文本是無效的Lua代碼;它應該用於調試/人工讀取。我想我可以在最後添加一個小鏈接或其他東西。 – kikito 2012-02-07 10:09:54

+1

向wiki添加了inspect.lua。 – kikito 2012-02-07 11:10:43

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

男人嗨,我寫了一個賽普爾代碼,在純Lua中做到這一點,它有一個bug(寫後昏迷列表中的最後一個元素),但是我如何快速將它寫成原型,我會讓它適應您的需求。

9

發現這一點:

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

作品對我來說相當不錯...

22

,我發現這是有用的。因爲如果遞歸它也可以打印嵌套表。

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長街,[ 「電話」] = 123456,[ 「名稱」] = Fred,},[2] = {[「address」] = 16 Long Street,[「phone」] = 123456,[「name」] = Wilma,},[3] = {[「address」] = 17 Long Street,[「phone」] = 123457,[「name」] = Barney,},}

2

這是我的版本,支持排除表和userdata

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

注意的是,根不刪除排除我見過

4

大多數純盧阿打印表函數深遞歸 存在問題,並且在去時傾向於導致堆棧溢出太深了。這個打印 我寫的表函數沒有這個問題。由於處理串聯的方式,它也應該能夠處理真正大的表。在我個人使用這個功能的時候,它在大約一秒鐘內輸出了63k行文件。

輸出也保持盧阿語法和腳本可以很容易地通過寫入輸出,如果修改,以允許 只有數字,布爾值,字符串和表數據類型被格式化爲文件進行修改 簡單的持久性存儲。

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 

下面是一個例子:

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' 
    } 
} 
1

正如前面提到的,你必須把它寫。 這是我謙虛的版本:(超基本一)

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

格式爲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

相關問題