Lua的table库函数insert、remove、concat、sort详细介绍(转载)

Lua的table库函数insert、remove、concat、sort详细介绍(转载)

函数列表:

table.insert(table,[ pos,] value) 
table.remove(table[, pos]) 
table.concat(table[, sep[, i[, j]]]) 
table.sort(table[, comp])

insert 和 remove 只能用于数组元素的插入和移出, 进行插入和移出时,会将后面的元素对齐起来。

    所以在 for 循环中进行 insert 和 remove 的时候要注意插入和移除时是否漏掉了某些项:

        local t = {1,2,3,3,5,3,6} 
        for i,v in ipairs(t) do 
            if v == 3 then 
                table.remove(t,i) 
            end 
        end 
        -- 错误,第四个 3 没有被移除,ipairs 内部会维护一个变量记录遍历的位置,remove 掉第三个数字 3 之后,ipairs 下一个返回的值是 5 而不是 3 
        
        local t = {1,2,3,3,5,3,6} 
        for i=1, #t do 
            if t[i] == 3 then 
                table.remove(t,i) 
                i = i-1 
            end 
        end 
        -- 错误,i=i-1 这段代码没有用,i 的值始终是从 1 到 #t,for 循环里修改 i 的值不起作用 
        
        local t = {1,2,3,3,5,3,6} 
        for i=#t, 1, -1 do 
            if t[i] == 3 then 
                table.remove(t,i) 
            end 
        end 
        -- 正确,从后往前遍历 
        
        local t = {1,2,3,3,5,3,6} 
        local i = 1 
        while t[i] do 
            if t[i] == 3 then 
                table.remove(t,i) 
            else 
                i = i+1 
            end 
        end 
        -- 正确,自己控制 i 的值是否增加 
    

 

concat 可以将 table 的数组部分拼接成一个字符串,中间用 seq 分隔。 
    lua 中字符串的存储方式与 C 不一样,lua 中的每个字符串都是单独的一个拷贝,拼接两个字符串会产生一个新的拷贝,如果拼接操作特别多,就会影响性能: 

 

        local beginTime = os.clock() 
        local str = "" 
        for i=1, 30000 do 
            str = str .. i 
        end 
        local endTime = os.clock() 
        print(endTime - beginTime) 
        -- 消耗 0.613 秒,产生了 30000 个字符串拷贝,但只有最后一个是有用的
        local beginTime = os.clock() 
        local t = {} 
        for i=1, 30000 do 
            t[i] = i 
        end 
        local str = table.concat(t, "") 
        local endTime = os.clock() 
        print(endTime - beginTime) 
        -- 消耗 0.024 秒,利用 concat,一次性把字符串拼接出来,只产生了一个字符串拷贝 
      

 

 sort 可以将 table 数组部分的元素进行排序,需要提供 comp 函数,comp(a, b) 如果 a 应该排到 b 前面,则 comp 要返回 true 。    
    注意,对于 a==b 的情况,一定要返回 false :

 

        local function comp(a,b) 
            return a <= b 
        end 
        table.sort(t,comp) 
        -- 错误,可能出现异常:attempt to compare number with nil 
        
        local function comp(a,b) 
            if a == nil or b == nil then 
                return false 
            end 
            return a <= b 
        end 
        table.sort(t,comp) 
        -- 错误,可能出现异常:invalid order function for sorting 
        -- 也可能不报这个异常,但结果是错误的; 
    之所以 a==b 返回true 会引发这些问题,是因为 table.sort 在实现快速排序时没有做边界检测: 
        for (;;) { 
          while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) {  // 未检测边界, i 会一直增加 
            if (i>=u) luaL_error(L, "invalid order function for sorting"); 
            lua_pop(L, 1); 
          } 
          while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) {  // 未检测边界, j 会一直减少 
            if (j<=l) luaL_error(L, "invalid order function for sorting"); 
            lua_pop(L, 1); 
          } 
          if (j<i) { 
            lua_pop(L, 3); 
            break; 
          } 
          set2(L, i, j); 
        } 
  

 

看以上代码,如果 a==b 时返回 true 且边界上的几个值是相等的话, sort_comp 就无法阻止 i 继续增长,直到超出边界引发异常 attempt to compare number with nil;即使我们对 a 和 b 进行非空判断,也会因为 i 超过边界而引发异常 invalid order function for sorting 

posted @ 2016-11-07 11:27 HaoK 阅读( ...) 评论( ...) 编辑 收藏
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值