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是指使用原生 ...
随机推荐
- nodejs豆瓣爬虫
从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎.chrome浏 ...
- 13.调整数组顺序使奇数位于偶数前面 Java
思路 两次遍历,第一次把奇数加到list中,第二次把偶数加到list中,时间复杂度为O(n). 利用类似于插入排序的方法,但时间复杂度为O(n^2). 代码 import java.util.Arra ...
- sql语句中where 1=1和 0=1 的作用
sql where 1=1和 0=1 的作用 where 1=1; 这个条件始终为True,在不定数量查询条件情况下,1=1可以很方便的规范语句. 一.不用where 1=1 在多条件查询中的 ...
- mysql 查询相关命令
1. 结果集按列展示 mysql -u用户名 -p密码 -D 数据库名 -e sql语句 示例:mysql -uroot -p123456 -D mysql -e select * f ...
- 20182303 2019-2020-1 《数据结构与面向对象程序设计》第2&3周学习总结
目录 教材学习内容总结 教材学习中的问题和解决过程 代码调试中的问题和解决过程 代码托管 上周考试错题总结 结对及互评 点评 学习进度条 教材学习内容总结 教材第二章内容 学习Java基本数据类型以及 ...
- Linux之profile、bash_profile、bashrc文件
来自: profile.bash_profile.bashrc文件的作用与区别 1. profile 文件 1.1 profile 文件的作用 profile(/etc/profile),用于设置系统 ...
- kotlin if
val max = if (a > b) { print("Choose a") a } else { print("Choose b") b } 注意和 ...
- Android Studio NDK编程-环境搭建及Hello!
一,下载 安装android-ndk开发包 NDK各个版本链接二,新建项目NDKDemo,选择空Activity就可以:(注:Android studio 2.2,可通过SDK Tools 添加LLD ...
- JavaScript如何封装插件
什么是封装呢? 我的理解就是 把一个功能单独做成一个组件,就像做饺子,以前做饺子必须自己先用面粉做饺子皮,再做饺子馅,然后再手工包饺子,但是现在人们发明了自动包饺子机器,虽然机器里面的每一步骤和你自己 ...
- 排错:Unable to create a new session key. It is likely that the cache is unavailable.
排错:Unable to create a new session key. It is likely that the cache is unavailable. 问题 登录openstack页面, ...