在工作中使用lua也有一年了,代码也写了不少,踩过不少坑,这里记录一下。

  • table.sort

  table.sort是lua自带的排序函数,数据量小时,也还是不错的。不过要注意你传入的compare函数。例如:

local tb = { ,,,,,,, }

table.sort( tb,function(a,b) return a>=b end )

上面的代码够简单了,但是你运行起来,却是报错了。

Program starting as '"D:\programs\ZeroBraneStudio\bin\lua53.exe" -e "io.stdout:setvbuf('no')" "D:\work_code\lua\Test\Test.lua"'.
Program 'lua53.exe' started in 'D:\work_code\server' (pid: ).
D:\programs\ZeroBraneStudio\bin\lua53.exe: D:\work_code\lua\Test\Test.lua:: invalid order function for sorting
stack traceback:
[C]: in function 'sort'
D:\work_code\lua\Test\Test.lua:: in main chunk
[C]: in ?
Program completed in 0.04 seconds (pid: ).

原因在于compare函数中不能出现等于,即a>b或a<b都OK,但不能是a>=b或a<=b。如果使用了=,当数组中出现两个权重一样的元素时,就会报错。具体原因你可以看table.sort的官方文档,有句话:

If comp is given, then it must be a function that receives two list elements and returns true when the first element must come before the second in the final order (so that, after the sort, i < j implies not comp(list[j],list[i]))

如果是报invalid order function for sorting也就罢了,网上查一下就能找到答案。然而我在项目中的报错却比较奇怪:

function Society_city:do_player_hurt_sort()
local player_hurt = {}
for ty,hurt_info in pairs( self.player_hurt ) do
for pid,info in pairs( hurt_info ) do
local _info = {}
_info.ty = ty
_info.pid = pid
_info.hurt = info.hurt
_info.times = info.times table.insert( player_hurt,_info )
end
end table.sort( player_hurt,function(a,b) return a.hurt >= b.hurt end ) return player_hurt
end

报错信息为:

society_city.lua:: attempt to index local 'a' (a nil value)

我一直以为是数组中加入了一个nil,但查了半天,原来是>=的原因。

  • table编译

在我们的项目中,策划将配置填到excel表,然后用工具将excel表批量转为lua表作为配置。这样在lua中直接require就可以使用配置了。转出来的配置表通常是这样的:

local t =
{
[] =
{
['id'] = ,
['icon'] = ,
['name'] = '默认头像框',
['description'] = '初始赠送',
['type_id'] = ,
['sort'] = ,
}, [] =
{
['id'] = ,
['icon'] = ,
['name'] = '10级头像框',
['description'] = '达到$1级即可获得',
['type_id'] = ,
['num'] = ,
['sort'] = ,
}, [] =
{
['id'] = ,
['icon'] = ,
['name'] = '20级头像框',
['description'] = '达到$1级即可获得',
['type_id'] = ,
['num'] = ,
['sort'] = ,
}, [] =
{
['id'] = ,
['icon'] = ,
['name'] = '30级头像框',
['description'] = '达到$1级即可获得',
['type_id'] = ,
['num'] = ,
['sort'] = ,
}, [] =
{
['id'] = ,
['icon'] = ,
['name'] = '40级头像框',
['description'] = '达到$1级即可获得',
['type_id'] = ,
['num'] = ,
['sort'] = ,
}, [] =
{
['id'] = ,
['icon'] = ,
['name'] = '50级头像框',
['description'] = '达到$1级即可获得',
['type_id'] = ,
['num'] = ,
['sort'] = ,
}, [] =
{
['id'] = ,
['icon'] = ,
['name'] = '60级头像框',
['description'] = '达到$1级即可获得',
['type_id'] = ,
['num'] = ,
['sort'] = ,
}, }

在某些功能中,是需要将id从小到大遍历的。由于策划配置时总是严格按小到大的,转换出来的配置表key值也是从小到大的。然而,当我们require这个table时,顺序却是乱的。即

for k,v in pairs( t ) do
print( k,v )
end

输出:

Program 'lua.exe' started in 'D:\work_code\server' (pid: ).
table: 0x003d8ff8
table: 0x003d92c8
table: 0x003d90e8
table: 0x003d8a58
table: 0x003da560
table: 0x003d91d8
table: 0x003d92f0
Program completed in 0.03 seconds (pid: ).

这样的代码,第一个取得的id并不一定是1。也就是说,lua虚拟机在编译这个文件时,里面的元素并不是按顺序的,即使key值是int型并且按从小到大并严格自增。

lua中的坑的更多相关文章

  1. Gink掉过的坑(一):将CCTableView导入到lua中

    环境: 系统:win7 64位 cocos2dx:cocos2d-2.1rc0-x-2.1.3 Visual Studio: 2012 由于项目是用lua写的,需要将cocos2dx中的方法导入到lu ...

  2. Torch-RNN运行过程中的坑 [2](Lua的string sub函数,读取中文失败,乱码?)

    0.踩坑背景 仍然是torch-rnn/LanguageModel.lua文件中的一些问题,仍然是这个狗血的LM:encode_string函数: function LM:encode_string( ...

  3. Torch-RNN运行过程中的坑 [1](读取Lua非空table,size为0)

    0.踩坑背景 执行Torch-RNN的时候,在LanguageModel.lua中的encode_string函数中,对start_text的各个character进行id映射编码,实现功能类似“北京 ...

  4. 在redis一致性hash(shard)中使用lua脚本的坑

    redis 2.8之前的版本,为了实现支持巨量数据缓存或者持久化,一般需要通过redis sharding模式来实现redis集群,普遍大家使用的是twitter开源的Twemproxy. twemp ...

  5. lua中遍历table的几种方式比较

    当我在工作中使用lua进行开发时,发现在lua中有4种方式遍历一个table,当然,从本质上来说其实都一样,只是形式不同,这四种方式分别是: for key, value in pairs(tbtes ...

  6. Torch-RNN运行过程中的坑 [0](一些基础概念)

    0.Lua & LuaJIT简介 Lua 是一种轻量小巧的脚本语言,用标准C语言编写并以源代码形式开放, 其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能. Lua 是巴 ...

  7. 从架构层面杜绝lua中使用未定义的变量

    # 从架构层面杜绝lua中使用未定义的变量 标签(空格分隔): lua --- lua中有一个很坑的地方:1.就是如果一个变量拼写错误,会自动的认为你定义了一个值为nil的全局变量.2.如果在func ...

  8. lua中基类和“继承机制”

    基类:基类定义了所有对于派生类来说普通的属性和方法,派生类从基类继承所需的属性和方法,且在派生类中增加新的属性和方法. 继承:继承是C++语言的一种重要机制,它允许在已定义的类的基础上产生新类. lu ...

  9. lua中实现异步资源读写

    同样还是更新方面的需求,当我们检测到版本是新安装的以后,要进行upd目录清除.如果使用os.execute执行 rm -rf ooxx 是非常快的但由于os.execute一旦报错,那整个lua进程就 ...

随机推荐

  1. 如何完全退出android应用程序

    当一个android应用程序包含多个activity时,要完全退出android应用程序,便要销毁掉所有的activity,下面是一种网上流传的比较经典完美的方法: 首先要定义一个继承Applicat ...

  2. Java基础知识强化26(1):Object类之Object类的概述

    1.Object类 类Object是类层次结构的根类,每个类都使用 Object作为超类.所有对象(包括数组)都实现这个类的方法 每个类直接或者间接继承自Object类   2.Object类无参构造 ...

  3. Win10系统修改MAC地址

    本地管理地址,输入想修改的MAC地址后,点确定即完成修改.在CMD窗口中,使用ipconfig 命令可以查看新的MAC地址. 再次钩选不存在,则还原为原来的MAC地址.

  4. MM32 备份域学习(兼容STM32)

    MM32 备份域学习(兼容STM32) 内容提要 备份域工作原理 备份域特性 备份域的保护:侵入检测 备份域侵入检测 备份域电源与主要内容 备份域特性 20字节数据后备寄存器(中容量和小容量产品),或 ...

  5. ssanf()的用法

    转载自http://www.cnblogs.com/lyq105/archive/2009/11/28/1612677.html 看着写着不错,就转了,保存一下 C语言函数sscanf()的用法 ss ...

  6. Wcf资料收集

    1.简介 http://www.tuicool.com/articles/mqYB32 使用规范 http://blog.51cto.com/zt/219 2.教程系列 http://www.cnbl ...

  7. 武汉科技大学ACM :1010: 零起点学算法12——求2个日期之间的天数

    Problem Description 水题 Input 输入2个日期,日期按照年月日,年月日之间用符号-隔开(题目包含多组数据) Output 求出这2个日期之间的天数(不包括自身),每组测试数据一 ...

  8. 函数递归时,递归次数到900多时,就是抛出异常exception RuntimeError('maximum recursion depth exceeded',)

    import subprocess import multiprocessing import urllib import sys import os import pymongo import si ...

  9. Mysql 5.7.9 cmake boost.cmake 处理

    环境Centos 6.7 x64 mininal 今天突然编译Mysql 5.7.9 按之前的cmake .的方式 发现报错了..提示 需要boost -- BOOST_INCLUDE_DIR /us ...

  10. jdbc接口api

    java.sql.* 和 javax.sql.* |- Driver接口: 表示java驱动程序接口.所有的具体的数据库厂商要来实现此接口. |- connect(url, properties): ...