Lua 打印 table (支持双向引用的table)
网上搜了一下,挺多打印table的方案,基本思路都是一层一层递归遍历table。(我就是参考这种思路做的^_^)
但大部分都不支持双向引用的打印。我所指的双向引用,就是a引用b, b又直接或间接引用a。例如下面的双向链表:
local node1 = {}
local node2 = {}
local node3 = {} node1.value =
node1.pre = nil
node1.next = node2 node2.value =
node2.pre = node1
node2.next = node3 node3.value =
node3.pre = node2
node3.next = nil
像这样一个双链表,网上的很多方法,处理这种情况时,递归无法结束。因为,node1 表里有个 node2, 遍历node2时,又发现有个node1,如此反复
那要怎么处理呢?我的方案是:把每个table的父级table用一个链表保存起来,当判断到当前要处理的table存在于父级链表里,就停止处理。
完整代码如下:
------ 把table转成string
-- sign 打印在最前面的一个标记
-- tab 待处理table
-- showAddress 是否显示table的地址
function TabToStr(sign, tab, showAddress) -- 缓存table地址,防止递归死循环
local tabs = {};
local check = function(cur_tab, key, parentKey, level)
local tempP = tabs[(level-) .. parentKey]
while tempP do
if tempP.id == tostring(cur_tab) then
return false;
end
tempP = tempP.parent;
end tabs[level .. key] = {};
tabs[level .. key].id = tostring(cur_tab);
tabs[level .. key].parent = tabs[(level-) .. parentKey]; return true;
end -- 处理直接传入table的情况
if tab == nil then
tab = sign;
sign = "table:";
end local targetType = type(tab);
if targetType == "table" then
local isHead = false;
local function dump(t, tKey, space, level)
local temp = {};
if not isHead then
temp = {sign or "table:"};
isHead = true;
end if tKey ~= "_fields" then
table.insert(temp, string.format("%s{", string.rep(" ", level)));
end
for k, v in pairs(t) do
local key = tostring(k);
-- 协议返回内容
if key == "_fields" then
local fields = {};
for fk, fv in pairs(v) do
fields[fk.name] = fv;
end
table.insert(temp, dump(fields, key, space, level))
-- 如果是table模拟的类,忽略。 以下划线开头的字段, 忽略
elseif key == "class" or string.sub(key, , string.len("_")) == "_" then
-- 这里忽略 elseif type(v) == "table" then
if check(v, key, tKey, level) then
if showAddress then
table.insert(temp, string.format("%s%s: %s\n%s", string.rep(" ", level+), key, tostring(v), dump(v, key, space, level + )));
else
table.insert(temp, string.format("%s%s: \n%s", string.rep(" ", level+), key, dump(v, key, space, level + )));
end
else
table.insert(temp, string.format("%s%s: %s (loop)", string.rep(" ", level+), key, tostring(v)));
end
else
table.insert(temp, string.format("%s%s: %s", string.rep(" ", level+), key, tostring(v)));
end
end
if tKey ~= "_fields" then
table.insert(temp, string.format("%s}", string.rep(" ", level)));
end return table.concat(temp, string.format("%s\n", space));
end
return dump(tab, "", "", );
else
return tostring(tab);
end
end
核心方法说明:
check 方法, 检测父级table链表中是否存在当前table
dump 方法, 递归遍历table
上面代码在实际项目中测试可用,一般情况可以直接使用。但有些是根据项目情况填充的内容。想要理解或改写的话,看下面的精简dump方法
local function dump(t, tKey, space, level)
local temp = {};
table.insert(temp, string.format("%s{", string.rep(" ", level)));
for k, v in pairs(t) do
local key = tostring(k);
if type(v) == "table" then
if check(v, key, tKey, level) then
table.insert(temp, string.format("%s%s: \n%s", string.rep(" ", level+), key, dump(v, key, space, level + )));
else
table.insert(temp, string.format("%s%s: %s (loop)", string.rep(" ", level+), key, tostring(v)));
end
else
table.insert(temp, string.format("%s%s: %s", string.rep(" ", level+), key, tostring(v)));
end
end
table.insert(temp, string.format("%s}", string.rep(" ", level)));
return table.concat(temp, string.format("%s\n", space));
end
测试:
tab = {, , , , {, , , }}
-- 这里的node1就是上面贴出的双向链表
print (TabToStr("node1", node1, true))
print (TabToStr("node1", node1))
print (TabToStr(tab))
结果:
Lua 打印 table (支持双向引用的table)的更多相关文章
- Lua table之弱引用
Lua采用了基于垃圾收集的内存管理机制,因此对于程序员来说,在很多时候内存问题都将不再困扰他们.然而任何垃圾收集器都不是万能的,在有些特殊情况下,垃圾收集器是无法准确的判断是否应该将当前对象清理.这样 ...
- Lua打印Table的数据结构工具类
--这是quick中的工具,作用就是打印Lua中强大的table的结构, 当table的嵌套层级比较多的时候,这个工具非常方便,开发中必备的工具. --具体使用方法:local debug = req ...
- Lua打印table树形结构
--这是quick中的工具,作用就是打印Lua中强大的table的结构, 当table的嵌套层级比较多的时候,这个工具非常方便,开发中必备的工具.--具体使用方法:local debug = requ ...
- lua序列化(支持循环引用)
lua序列化 支持key类型为string, number 支持value类型为string, number, table, boolean 支持循环引用 支持加密序列化 支持loadstring反序 ...
- lua 怎样输出树状结构的table?
为了让游戏前端数据输出更加条理,做了一个简单树状结构来打印数据. ccmlog.lua local function __tostring(value, indent, vmap) local str ...
- lua 与C通过c api传递table (2)
本文转自http://blog.csdn.net/a_asinceo/article/details/49907903(感谢...) 一.单个参数的传递 首先我们在Lua中注册一个C类PJYCallb ...
- 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(上)
前言: 好久没写文章了,最近先是重构IT恋.又重写IT恋中. Sagit框架也不断的更新,调整,现在感觉已完美了了相当的多. 今天不写教程,先简单分享一下技术内容. 1:见Block必有:#defin ...
- 讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(下)- block中任性用self
前言: 在处理完框架内存泄漏的问题后,见上篇:讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(中)- IOS不为人知的Bug 发现业务代码有一个地方的内存没释放,原因很也简单: ...
- css Table布局:基于display:table的CSS布局
两种类型的表格布局 你有两种方式使用表格布局 -HTML Table(<table>标签)和CSS Table(display:table 等相关属性). HTML Table是指使用原生 ...
随机推荐
- 适配iphone X
首先需要为meta标签加上viewport-fit=cover,默认viewport-fit=contain,跟background-size类似.当值设置为cover既可让安全区域铺满全屏,就跟适配 ...
- nginx实现负载均衡、缓存功能实战
nginx实现负载均衡.缓存功能实战 什么是正向代理?应用场景:翻墙 什么是反向代理?例如:haproxy和nginx Nginx实现反向代理 nginx代理基于是ngx_http_proxy_m ...
- Nginx之最简单的反向代理机制分析
注:当前分析基于 Nginx之搭建反向代理实现tomcat分布式集群 的配置. 1. 用到的指令 下面介绍在上面的配置中用到的指令. upstream 指令 语法:upstream name { .. ...
- Nginx之进程间的通信机制(信号、信号量、文件锁)
1. 信号 Nginx 在管理 master 进程和 worker 进程时大量使用了信号.Linux 定义的前 31 个信号是最常用的,Nginx 则通过重定义其中一些信号的处理方法来使用吸纳后,如接 ...
- python 格式化输出用户名/密码
格式化输出用户名/密码 内容来自网络 def get_account(num): accounts = [] for index in range(1, num+1): accounts.append ...
- 7.Mahout菩萨
1.Maout简介 2.机器学习介绍 3.Mahout算法介绍
- 用key管理可复用元素
先看看不用key管理可复用元素的代码.Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染.这么做,除了使 Vue 变得非常快之外,还有一些有用的好处,那就是在切换input时不会清楚 ...
- Log统一管理类
import android.util.Log; /** * Log统一管理类 */ public class L{ private L(){ /* cannot be instantiated */ ...
- Pattern Evaluation
对相关性patten质量的常用分析指标有以下这些 其中,X^2 跟 lift不是null-invariant的,也就是说当~A~B项较多时,这两个指标不是很可靠. 据Jiawei Han所言,Kulc ...
- ZeroMQ——一个轻量级的消息通信组件 C#
ZeroMQ——一个轻量级的消息通信组件 ZeroMQ是一个轻量级的消息通信组件,尽管名字中包含了"MQ",严格上来讲ZeroMQ并不是"消息队列/消息中间件" ...