|
发表于 2023-5-25 22:54:59
|
显示全部楼层
本帖最后由 无名拉二胡#7884 于 2023-5-26 09:06 编辑
另外提供一套元方法,使用tbl=set_ordered_metatable(tbl) 激活,该表格具有一些元方法功能
function set_ordered_metatable(tbl)
local keys = {} -- 有序键列表
local nkeys={}
local index=0
local newtab={}
local data={}
local function get_index(key)
if not key then
key=tostring(index+1)
end
if not keys[key] then
index=index+1
keys[key]=index
nkeys[index]=key
end
return keys[key]
end
local function tabmakenil(key)
local id=keys[key]
if id then
keys[key]=nil
local value=data[id]
data[id]=data[index]
data[index]=nil
nkeys[id]=nkeys[index]
nkeys[index]=nil
index=index-1
return(value)
end
end
local default_cursor=1
local func = function ( tbl,key )
default_cursor = default_cursor + 1
return nkeys[default_cursor],data[default_cursor]
end
local mt = {
__index = function(t, key)
if type(key)~="number" then
return data[keys[key]]
end
return data[keys[tostring(key)]]
end,
__newindex = function(t, key, value)
if type(key)=="number" then
key=tostring(key)
end
if value then
data[get_index(key)]=value -- 更新表中的键值对
else
tabmakenil(key)
end
end,
__pairs = function ( tbl,key )
default_cursor=0
return func,tbl
end,
__sub=function(tbl,key)
local value
if type(key)~="number" then
value=tabmakenil(key)
else
value=tabmakenil(nkeys[key])
end
return(value)
end,
__add=function(tbl,value)
local index= get_index()
data[index]=value
-- 更新表中的键值对
return(index)
end,
__div=function(tbl,value) --从表中移除指定值
local key
for k,v in ipairs(tbl) do
if v==value then
key=k
break
end
end
if key then --如果值存在,具有索引
return nkeys[key],tbl-key
end
end,
__call=function(tbl,str)
if str=="copy" then
local ntab={}
ntab=set_ordered_metatable(ntab)
for k,v in pairs(tbl) do
ntab[k]=v
end
return(ntab)
end
end,
__len=function(tbl)
return(#data)
end,
__mod=function(tbl,key)
return nkeys[key]
end,
}
setmetatable(newtab, mt)
for key, _ in old_pairs(tbl) do
table.insert(nkeys, key)
end
table.sort(nkeys, function(a, b)
-- 比较字节码整数
a=tostring(a)
b=tostring(b)
return string.lbyte(a, 1, #a) < string.lbyte(b, 1, #b)
end)
for i=1,#nkeys do
if type(tbl[nkeys])=="table" then
newtab[nkeys]=set_ordered_metatable(tbl[nkeys])
else
newtab[nkeys]=tbl[nkeys]
end
end
return newtab
end
|
|