刚学lua不久,导师布置的一个作业,实现一个能处理table的print
--[[
evn:Lua 5.1
]]
function prettystring(...)
for key, value in pairs({...}) do
prettyOneString(value)
end
end
function prettyOneString(data,onlyTable,tab) --data处理的数据,onlyTable记录表,tab为tab数量
printTab = function (n)
for i=0,n do
io.write(" ") --tab
end
end
if onlyTable == nil then
onlyTable = {}
end
if(tab == nil) then
tab = 0
end
if type(data) ~= 'table' then --非table情况
if type(data) == 'string' then
io.write(data)
else
io.write(tostring(data))
end
if tab ~= 0 then --处理table成员末尾的逗号
io.write(",")
end
io.write("\n")
else --处理table
io.write("{\n")
if next(data) ~= nil and not findTableValue(onlyTable,data) then
table.insert(onlyTable,data) --坑:是table.insert(),不是table成员.insert()
for index, value in pairs(data) do
if type(index) == 'string' then
printTab(tab)
io.write("[\""..tostring(index).."\"] " .. "= ")
else
printTab(tab)
io.write("["..tostring(index).."] " .. "= ")
end
prettyOneString(value,onlyTable,tab+1)
end
end
printTab(tab-1) --格式对齐
io.write("},\n")
end
end
function findTableValue(table,findValue) --寻找value是否在table中
if next(table) == nil then
return false
end
for key, value in pairs(table) do
if value == findValue then
return true
end
return false
end
end
但是还是有几个地方有问题。
- 没用使用local修饰局部变量
- 字符串…连接消耗性能大,最好用table.concat()
- 寻找循环引用表可以使用 {[table] = “@/位置”} 的方式,一方面优化了查询时间,另一方面可以之间找到表第一次出现的位置
- paris无法处理nil,必须使用select("#",…)
- 给table添加手动计数器,取代#table,但是可读性个人觉得会差一点
修改后为
local function prettystring(...)
local tinsert = table.insert
local uniqueTable = {}
local function prettyOneString(data,tab,path)
tab = tab or 0
path = path or "@/"
local retTable = {} --存储最后的结果
if type(data) ~= 'table' then --处理非table
tinsert(retTable ,tostring(data))
if tab ~= 0 then
tinsert(retTable,",")
end
else --处理table
if uniqueTable[tostring(data)] == nil then
tinsert(retTable,"{\n")
end
if next(data) ~= nil and uniqueTable[tostring(data)] == nil then
uniqueTable[tostring(data)] = path
for key, value in pairs(data) do
tinsert(retTable,string.rep("\t",tab))
if type(key) == 'string' then
local tmpString = string.format('["%s"] = ',tostring(key)) --string.format可读性会比较好点,性能略微损失
tinsert(retTable,tmpString)
else
local tmpString = string.format("[%s] = ",tostring(key))
tinsert(retTable,tmpString)
end
tinsert(retTable,prettyOneString(value,tab+1,path..tostring(key)..'/' ))
tinsert(retTable,"\n")
end
local tmpString = string.format("%s},",string.rep("\t",tab))
tinsert(retTable,tmpString)
else
local tmpString = string.format("%s",uniqueTable[tostring(data)])
tinsert(retTable,tmpString)
end
end
return table.concat(retTable)
end
--start
local argv = table.pack(...)
for i=1,argv.n do --遍历参数
local argcType = type(argv[i])
if argcType == 'table' and i ~= 1 then
io.write("\n")
end
io.write(prettyOneString(argv[i]))
if argcType ~= 'table' and i ~= argv.n then
io.write("\t") --模拟print行为
end
end
io.write("\n")
end
return prettystring