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是指使用原生 ...
随机推荐
- ARTS打卡计划第八周
Algorithms: https://leetcode-cn.com/problems/repeated-substring-pattern/ 重复子字符串 Review: “I’m Leavin ...
- 图解golang内存分配机制 (转)
一般程序的内存分配 在讲Golang的内存分配之前,让我们先来看看一般程序的内存分布情况: 以上是程序内存的逻辑分类情况. 我们再来看看一般程序的内存的真实(真实逻辑)图: Go的内存分配核心思想 G ...
- Bootstrap视频教程
一.全局CSS样式 0.课件 001.概览_栅格系统 2.排版和代码 3.表格和按钮 4.表单 5.图片 6.辅助类 7.响应式工具 二.组件 8.图标_下拉菜单_按钮组 9.输入框组 10.导航 1 ...
- [MyBatis]完整MyBatis CRUD工程
下载地址:https://files.cnblogs.com/files/xiandedanteng/Person191005.rar pom.xml:这个文件主要是引入依赖 <project ...
- 2.2 Go语言基础之位运算操作
一.位运算符 位运算符对整数在内存中的二进制位进行操作. 运算符 描述 & 参与运算的两数各对应的二进位相与. (两位均为1才为1) | 参与运算的两数各对应的二进位相或. (两位有一个为1就 ...
- Oracle 中的进制转换
Oracle 中的进制转换 */--> Oracle 中的进制转换 Table of Contents 1. 进制名 2. 10进制与16进制互相转换 2.1. 10进制转换为16进制 2.2. ...
- Smarty section、foreach控制循环次数的实现详解
<!--{ section name='i' loop=$a }--><!--{ if $smarty.section.i.index < 3 }--><!--{ ...
- a lot of attention under the hood
Because one of the original goals of the Node.js project was to allow developers to easily build app ...
- 一百零七:CMS系统之权限和角色模型定义
模型与权限关系映射表 class CMSPersmission: """ 权限管理映射 """ # 255的二进制方式来表示 1111 11 ...
- centos 系统字体库安装中文字体
一,centos系统默认不支持中文字体的,需要手动安装windows系统中的中文字体库到centos中. 首先,将windows系统中的字体拷贝出来: windows:打开C:\Windows\Fon ...