9

主题

17

回帖

881

积分

优秀创作者

积分
881

夏日·闪闪发光勋章

发表于  2023-5-25 22:53:24 | 显示全部楼层 |阅读模式 7933 7
本帖最后由 无名拉二胡#7884 于 2023-5-26 09:20 编辑

抄完生效,远离异步
测试lua的math.random不会异步,而pairs具有字符串key的table,尤其是从xlxs这种文件搞进来的表(我就是)很容易异步
需要重新定义pairs

local old_pairs = pairs --记录原来的pairs
pairs = function(tbl,key) --新pairs
  
  local keylist=is_table_ordered(tbl)--是否乱序列表

  if  keylist then --是乱序列表
  
local lbytes={} --计算字节整数并存储
      table.sort(keylist, function(a, b) --按照字节整数排序
      -- 比较字节码整数
      a=tostring(a)
      b=tostring(b)
      lbytes[a]=lbytes[a] or string.lbyte(a, 1, #a)  --计算字节整数并存储到列表,不重复计算
      lbytes=lbytes or string.lbyte(b, 1, #b)
      
     
      return lbytes[a] < lbytes

end)
   local cursor=0  --指针初始化
  return  function( tbl,key ) --开始遍历
  cursor = cursor + 1
  local k=keylist[cursor]
  return k,tbl[k] --返回键和值
  end,tbl

  end
  return old_pairs(tbl,key)
end
function string.lbyte(a)   --获得字节码整数,方便比较大小排序
  local tab={string.byte(a,1,#a)}
  local num=0
  for k,v in ipairs(tab) do
   
num = num * 256 + v

   
  end
  return(num)
end
function is_table_ordered(tbl)    --判断table是否定序,如果非定序,返回键表
  local length = #tbl  -- 表的长度


  -- 遍历表的整数索引,存储到 keys 表中
  local n=0
  local keylist={}
  for key, _ in old_pairs(tbl) do
      n=n+1
      keylist[n]=key
  end
  if n~=length then
     return keylist  -- 存在不连续的索引,表是乱序的
  end

  return nil  -- 表是按顺序排列的
end

9

主题

17

回帖

881

积分

优秀创作者

积分
881

夏日·闪闪发光勋章

发表于  2023-5-25 22:53:56 | 显示全部楼层
本帖最后由 无名拉二胡#7884 于 2023-5-26 00:17 编辑

原来写的太麻烦了,1楼其实就够了

9

主题

17

回帖

881

积分

优秀创作者

积分
881

夏日·闪闪发光勋章

发表于  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

9

主题

17

回帖

881

积分

优秀创作者

积分
881

夏日·闪闪发光勋章

发表于  2023-5-25 22:56:19 | 显示全部楼层
本帖最后由 无名拉二胡#7884 于 2023-5-26 00:18 编辑

其实就是key按照字节码排序

9

主题

17

回帖

881

积分

优秀创作者

积分
881

夏日·闪闪发光勋章

发表于  2023-5-25 22:56:39 | 显示全部楼层
抄完就行了,随便pairs,开始无敌

3

主题

70

回帖

280

积分

管理员

【问题收集】

积分
280
发表于  2023-5-26 10:37:32 | 显示全部楼层
已加精

0

主题

1

回帖

13

积分

普通创作者

积分
13
发表于  2023-6-1 10:12:46 | 显示全部楼层
牛逼啊,收下先

0

主题

1

回帖

15

积分

普通创作者

积分
15
发表于  2023-7-5 12:54:19 | 显示全部楼层
牛逼牛逼 大佬确实厉害 !