在工作中使用lua也有一年了,代码也写了不少,踩过不少坑,这里记录一下。
- table.sort
table.sort是lua自带的排序函数,数据量小时,也还是不错的。不过要注意你传入的compare函数。例如:
local tb = { 9,8,3,777,0,36548,556,0 } 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: 6572). D:\programs\ZeroBraneStudio\bin\lua53.exe: D:\work_code\lua\Test\Test.lua:77: invalid order function for sorting stack traceback: [C]: in function 'sort' D:\work_code\lua\Test\Test.lua:77: in main chunk [C]: in ? Program completed in 0.04 seconds (pid: 6572).
原因在于compare函数中不能出现等于,即a>b或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:679: attempt to index local 'a' (a nil value)
我一直以为是数组中加入了一个nil,但查了半天,原来是>=的原因。
- table编译
在我们的项目中,策划将配置填到excel表,然后用工具将excel表批量转为lua表作为配置。这样在lua中直接require就可以使用配置了。转出来的配置表通常是这样的:
local t = { [1] = { ['id'] = 1, ['icon'] = 1001, ['name'] = '默认头像框', ['description'] = '初始赠送', ['type_id'] = 1, ['sort'] = 1, }, [2] = { ['id'] = 2, ['icon'] = 1002, ['name'] = '10级头像框', ['description'] = '达到$1级即可获得', ['type_id'] = 2, ['num'] = 10, ['sort'] = 2, }, [3] = { ['id'] = 3, ['icon'] = 1003, ['name'] = '20级头像框', ['description'] = '达到$1级即可获得', ['type_id'] = 2, ['num'] = 20, ['sort'] = 3, }, [4] = { ['id'] = 4, ['icon'] = 1004, ['name'] = '30级头像框', ['description'] = '达到$1级即可获得', ['type_id'] = 2, ['num'] = 30, ['sort'] = 4, }, [5] = { ['id'] = 5, ['icon'] = 1005, ['name'] = '40级头像框', ['description'] = '达到$1级即可获得', ['type_id'] = 2, ['num'] = 40, ['sort'] = 5, }, [6] = { ['id'] = 6, ['icon'] = 1006, ['name'] = '50级头像框', ['description'] = '达到$1级即可获得', ['type_id'] = 2, ['num'] = 50, ['sort'] = 6, }, [7] = { ['id'] = 7, ['icon'] = 1007, ['name'] = '60级头像框', ['description'] = '达到$1级即可获得', ['type_id'] = 2, ['num'] = 60, ['sort'] = 7, }, }
在某些功能中,是需要将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: 8044). 2 table: 0x003d8ff8 5 table: 0x003d92c8 3 table: 0x003d90e8 7 table: 0x003d8a58 1 table: 0x003da560 4 table: 0x003d91d8 6 table: 0x003d92f0 Program completed in 0.03 seconds (pid: 8044).
这样的代码,第一个取得的id并不一定是1。也就是说,lua虚拟机在编译这个文件时,里面的元素并不是按顺序的,即使key值是int型并且按从小到大并严格自增。