明天新功能就要上了,结果刚刚突然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. ubuntu 安装 oracle-xe-universal

    安装oracle-xe-universal第一个我们要考虑的就是交换分区是否足够大, 如果你直接安装,可能会出现下面的英文提示: This system does not meet the minim ...

  2. VS与SQL资源

    经常在网上看到有同学费尽心思的找SQL server数据库各版本的下载地址,看到别人的求助贴就不自觉的想去帮助他们,但是一个一个去帮助又不太现实,毕竟个人精力有限,既然大家有需求,那么笔者就本着乐于分 ...

  3. Linux安装ElasticSearch-2.2.0

    1.下载ElasticSearch-2.2.0安装包 https://www.elastic.co/downloads/elasticsearch 2.安装ElasticSearch-2.2.0 rp ...

  4. 【Linux】字符转换命令paste

    这个 paste 就要比join 简单多了!相对于 join 必须要比对两个文件的数据相关性, paste 就直接『将两行贴在一起,且中间以 [tab] 键隔开』而已!简单的使用方法: [root@w ...

  5. thinkphp日志分析

    #!/usr/bin/perl -w use strict; use warnings; use Tie::File; #### # Thinkphp日志分析 # 日志基本格式:{$now} &quo ...

  6. 【转】我的第一次和最后一次 Hackathon 经历

    我的第一次和最后一次 Hackathon 经历 在旧金山地区经常有一些叫做“Hackathon”的活动,吸引挺多人参加.我一直听说这个名字,可是一直不知道它到底是什么.我从来对竞赛式的活动不感兴趣,我 ...

  7. process credentials(三)

    主要内容包括: 1.进程描述符中Realtime Mutex相关数据结构的初始化 2.子进程如何复制父进程的credentials 3.per-task delay accounting的处理 4.子 ...

  8. hdu 3183 A Magic Lamp(RMQ)

    A Magic Lamp                                                                               Time Limi ...

  9. 还没被玩坏的robobrowser(2)——安装及快速开始

    安装robobrowser 注意:这里假设你知道如何使用pip安装python的库的知识,如果你不了解这一块的话,点这里获取帮助. 强烈推荐使用pip安装. pip install robobrows ...

  10. nginx 443 https mark

    #user  nobody; worker_processes  4; #error_log  logs/error.log; #error_log  logs/error.log  notice; ...