早已实现,想到个好的方式。兼顾可读性、折叠。
流程:
- 分析出单例、多引用,编号,仅考虑后者。
- 代码执行顺序固定,如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
local o='' local function p(i) o=o..i end assert({ p'1', a={ p'2', b={p'3'}, p'4' }, } and o=='1234')
- 在首次使用处插入定义,如 R(i,{..}) ,在后续引用处仅仅使用 R[i] 即可。
- 对测试例 t={} t[t]=t t.T=t 生成的代码如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
local R=setmetatable({},{ __index=function(R,id) R[id]={} return R[id] end, __call=function(R,id,t) if rawget(R,id) then for k,v in pairs(t) do--copy R[id][k]=v end t=R[id] end R[id]=t return t end, }) return R(1,{[R[1]]=R[1],["T"]=R[1],})
脚本(100行,含缩进、键、数组优化、测试,未支持函数)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
--by RobertL https://www.cnblogs.com/RobertL/p/14258259.html local T,P,I,F,SF,C,RP=type,pairs,table.insert,math.floor,string.format,table.concat,string.rep function D(d)--data to string local ts={--[[tables [t]=true/false,--has reference [id]=true/flase,--could refer (or define at first time) ]]} local t local function S(i)--scan(input) t=T(i) if t=='table' or (t=='string' and i:len()>10) then if not ts[i] then ts[i]=ts[i]==false else return end if t=='table' then for k,v in P(i) do S(k);S(v) end end end end S(d) --generate id, clean single instance local id=1 for t,r in pairs(ts) do if r then ts[t],id=id,id+1 else ts[t]=nil end end local o={--output list [[--Generated using Data2String2.lua by RobertL local _=setmetatable({},{ __index=function(R,id) R[id]={} return R[id] end, __call=function(R,id,t) if rawget(R,id) then for k,v in pairs(t) do--copy R[id][k]=v end t=R[id] end R[id]=t return t end, }) return ]]} local function W(t)--write if T(t)=='boolean' then print'her' end t=t=='' and ' ' or t I(o,t) end local function I(n)--indent(number) W(RP(' ',n)) end local function R(i,n,c)--reference(input,config,indent number,cofiger) t=T(i) local id=t~='number' and ts[i] if id then W'_' if ts[id] then W'['W(id)W']' return else W'('W(id)W',' ts[id]=id end end if t=='string' then W(SF('%q',i)) elseif t=='number' then if i==F(i) then i=F(i)--convert to integer end W(i) elseif t=='boolean' then W(i and 'true' or 'false') elseif t=='nil' then W'nil' elseif t=='table' then W'{' local is={} for ix,v in ipairs(i) do W''I(n+1) R(v,n+1)W',' is[ix]=true end for k,v in P(i) do if not is[k] then W''I(n+1) if not (T(k)=='string' and SF(k,'^[%a_]%w*$') and (W(k) or true)) then W'['R(k,n+1)W']' end W'='R(v,n+1)W',' end end W''I(n)W'}' end if id then W')' end end R(d,0) return C(o) end if not ... then local t={} t[t]=t t.T=t local t2=load(D(t))() assert(t2[t2]==t2 and t2.T==t2) -- t={} t.T={T1=t} t2=load(D(t))() assert(t2.T.T1==t2) -- t={a=1.0,b='string','long long string','long long string',[{[false]=false,false,}]=false} print(D(t)) end return D
待,支持外部引用,内部依赖检测。
格式测试:
t={['a key']=1.0,'short string','long long string','long long string',[{[false]=false,false,}]=false}
有
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
return { "short string", _(1,"long long string"--[[2]]), _[1], [{ false, [false]=false, }]=false, ["a key"]=1, }