Created
May 11, 2024 11:17
-
-
Save cloudwu/4c55ab0015e8011389770830cb24a923 to your computer and use it in GitHub Desktop.
A function in Lua similar to PHP's print_r
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local function keys(o) | |
local len = #o | |
local skeys = {} | |
local ukeys = {} | |
local n = 1 | |
for k,v in pairs(o) do | |
local nk = math.tointeger(k) | |
if nk == nil or nk <= 0 or nk > len then | |
local sk = tostring(k) | |
if type(k) == "string" then | |
skeys[n] = k; n = n + 1 | |
else | |
ukeys[k] = true | |
end | |
end | |
end | |
table.sort(skeys) | |
for k in pairs(ukeys) do | |
skeys[n] = k; n = n + 1 | |
end | |
return skeys | |
end | |
local function try_no_circular(o) | |
local cache = {} | |
local function seri_no_circular(o) | |
assert(cache[o] == nil, cache) | |
if type(o) == "table" then | |
local result = { "{" } | |
local n = 2 | |
cache[o] = true | |
for i = 1, #o do | |
local v = o[i] | |
result[n] = seri_no_circular(v); n = n + 1 | |
result[n] = " "; n = n + 1 | |
end | |
local key = keys(o) | |
for i = 1, #key do | |
local k = key[i] | |
local v = seri_no_circular(o[k]) | |
result[n] = seri_no_circular(k); n = n + 1 | |
result[n] = ":"; n = n + 1 | |
result[n] = v; n = n + 1 | |
result[n] = " "; n = n + 1 | |
end | |
result[n] = "}" | |
return table.concat(result) | |
else | |
return tostring(o) | |
end | |
end | |
local ok, r = pcall(seri_no_circular, o) | |
if not ok then | |
if r == cache then | |
return | |
else | |
error(r) | |
end | |
end | |
return r | |
end | |
local function mark_circular(o) | |
local cache = {} | |
local n = 1 | |
local function mark(o) | |
if type(o) == "table" then | |
local v = cache[o] | |
if v == nil then | |
cache[o] = false | |
else | |
if v == false then | |
cache[o] = n; n = n + 1 | |
end | |
return | |
end | |
for k,v in pairs(o) do | |
mark(k) | |
mark(v) | |
end | |
end | |
end | |
mark(o) | |
for k,v in pairs(cache) do | |
if not v then | |
cache[k] = nil | |
end | |
end | |
return cache | |
end | |
local function seri_circular(o) | |
local cache = mark_circular(o) | |
local function seri_object(o) | |
if type(o) ~= "table" then | |
return tostring(o) | |
end | |
local result | |
local s = cache[o] | |
if s then | |
if type(s) == "number" then | |
result = { "#"..s.."{" } | |
cache[o] = "[#"..s.."]" | |
else | |
return s | |
end | |
else | |
result = { "{" } | |
end | |
local n = 2 | |
for i = 1, #o do | |
local v = o[i] | |
result[n] = seri_object(v); n = n + 1 | |
result[n] = " "; n = n + 1 | |
end | |
local key = keys(o) | |
for i = 1, #key do | |
local k = key[i] | |
local v = seri_object(o[k]) | |
result[n] = seri_object(k); n = n + 1 | |
result[n] = ":"; n = n + 1 | |
result[n] = v; n = n + 1 | |
result[n] = " "; n = n + 1 | |
end | |
result[n] = "}" | |
return table.concat(result) | |
end | |
return seri_object(o) | |
end | |
local function seri(o) | |
return try_no_circular(o) or seri_circular(o) | |
end | |
function print_r(...) | |
local len = select("#", ...) | |
if len == 1 then | |
print(seri(...)) | |
else | |
local r = {} | |
local n = 1 | |
for i = 1, len do | |
local o = select(i, ...) | |
r[n] = seri(o); n = n + 1 | |
end | |
print(table.concat(r, "\t")) | |
end | |
end | |
-- test | |
local obj = {} | |
a = { 1,2,3, x=obj, y=obj, z={}, [obj] = 4 } | |
print_r(a) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment