明天新功能就要上了,结果刚刚突然QA说项目抛出了错误。握草,吓得立马出了一身汗。

查了一下错误,发现可能是自己写的不稳定排序造成的。自己感觉应该就是。把排序方法写成稳定的之后,代码分离编译进手机,跑了一下木有错误了。脑残的自己为何要对服务器传过来的有序数据进行排序呢?脑抽不明。

下文为转的别人总结的lua库。(该学习的地方还太多)

lua的table库

函数列表: 
table.insert(table,[ pos,] value) 
table.remove(table[, pos]) 
table.concat(table[, sep[, i[, j]]]) 
table.sort(table[, comp])


1. 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 的值是否增加


2. 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,一次性把字符串拼接出来,只产生了一个字符串拷贝


3. 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 
    快速排序是什么,lua 如何实现快速排序,可以参考 lua 源码中的描述,这里不多介绍;

---------------------------------------------

所以代码可以写成

  local function comp(a,b)
if a == nil or b == nil then
return false
end
if a == b then
     return false
    end
return a < b
end
table.sort(t,comp)

意思就是,在a == b 时,不进行交换就可以了。交换的话,就会导致不稳定。

Lua 自己实现排序sort比较方法,抛出错误invalid order function for sorting的更多相关文章

  1. 外部无法捕捉Realm的doGetAuthenticationInfo方法抛出的异常

    shiro权限框架,用户登录方法的subject.login(token)会进入自定义的UserNamePasswordRealm类的doGetAuthenticationInfo身份验证方法 通常情 ...

  2. Effective Java 第三版——74. 文档化每个方法抛出的所有异常

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  3. 《从零开始学Swift》学习笔记(Day54)——抛出错误

    原创文章,欢迎转载.转载请注明:关东升的博客 能放到try后面调用函数或方法都是有要求的,他们是有可能抛出错误,在这些函数或方法声明的参数后面要加上throws关键字,表示这个函数或方法可以抛出错误. ...

  4. Python错误 -- try/except/finally 、调用栈、记录错误、抛出错误

    Bug:程序编写有问题造成的错误,称之为Bug.    debug:调试 注意:bug是程序本身有问题.有缺陷.系统漏洞 异常:完全无法在程序运行中预测的错误,例如写入文件的时候,磁盘满了,写不进去了 ...

  5. PostgreSQL 抛出错误信息(错误行号)

    抛出错误行号是我们在写SQL中常用到的,在SQL Server和Oracle中都很简单,但是在PostgreSQL怎么实现呢?在网上查了下资料只有pg_exception_context包含错误行,我 ...

  6. 错误try……except……else……finally 记录错误logging 抛出错误raise

    1.错误处理机制 try--except--finally 格式: try: 可能出错的代码 except xxx1Error as e: 处理1 except xxx2Error as e: 处理2 ...

  7. 【Java】ArrayList 的 toArray() 方法抛出 ClassCastException 异常

    第一次用这个方法,结果冒出个莫名其妙的异常来: String[] names = (String[]) mTags.toArray(); 结果会抛出 java.lang.ClassCastExcept ...

  8. JUnit 判断方法抛出的异常

    :比方案1更详细,可以进一步判断抛出的异常的报错信息是否符合预期 不用上面那个属性,用 try - catch(因为判断了报错信息,所以不用判断异常的类型了吧) ( 注释:MyAssert类是我自定义 ...

  9. [Go] 如何正确地 抛出 错误 和 异常(error/panic/recover)?

    序言 错误 和 异常 是两个不同的概念,非常容易混淆.很多程序员习惯将一切非正常情况都看做错误,而不区分错误和异常,即使程序中可能有异常抛出,也将异常及时捕获并转换成错误.从表面上看,一切皆错误的思路 ...

随机推荐

  1. 【TP3.2 + 其他任何PHP框架】编辑、删除、添加数据,返回原分页 (ajax+form两种方式提交均可以)

    1.目的1:在如下的一个页面中,p=2,比如我们删除数据id=13,通过ajax提交{id,p} 这2个参数,就可以了,页面返回json的url参数中原样带上p即可. 2.目的2: 步骤1:在如下页面 ...

  2. 腾讯alloyteam团队前端代码规范

    来源于:http://alloyteam.github.io/CodeGuide/ 命名规则 项目命名 全部采用小写方式, 以下划线分隔. 例:my_project_name 目录命名 参照项目命名规 ...

  3. swift类型转换之Could not cast value of type xxx to xxx错误的一种特殊情况记录

    之前swift项目打包成Framework静态库,提供给OC项目套入使用时,有时会抱这样一个错误: 这个错误发生的概率比较随机,有时会,有时不会,而且这句话在swift中的使用,是做model类型强制 ...

  4. 整理打印PI值

    准备锻炼背诵PI的小数,找到PI值: PI=3. 141592653589793238462643383279502884197169399375105820974944592307816406286 ...

  5. Category在项目中的实际运用

    先看两行代码:1. label2.textColor = [UIColor colorWithHexString:@"707070"]; 2. _table.header = [M ...

  6. ss is one another utility to investigate sockets(特适合大规模tcp链接)

    原创文章,转载请注明: 转载自系统技术非业余研究 本文链接地址: ss is one another utility to investigate sockets(特适合大规模tcp链接) 具体的可以 ...

  7. Snip for Mac(桌面截图工具)安装

    1.软件简介    Snip 一款用于桌面截图的工具. 2.资源列表 链接 提取密码 系统要求 软件语言 Snip for Mac v2.0 (5771) fgab macOS 10.6.8 及以上 ...

  8. python练习笔记——组合恒等式

    排列组合结合恒等式 已知从n个物品中取出m个,则存在一个组合恒等式. C(n, m)=C(n, n-m)=C(n-1, m-1)+C(n-1,m) 其中C(n,0) = 1 求:从5取3 和 10 取 ...

  9. Unix考古记:一个“遗失”的shell

    谨以此文纪念伟大的计算机科学巨匠Ken Thompson和Dennis Ritchie,并同时向其他所有为Unix发展做出贡献的黑客致敬. 历史的尘埃 Unix作为一个举世闻名的操作系统已有40余年的 ...

  10. Openssl aes加解密例程 更进一步

    原文链接: http://blog.csdn.net/itmes/article/details/7718427 前面我们用openssl的aes256对称加密算法对16个字节的内存块进行了的加解密运 ...