前言
这两天碰到一个问题。发现游戏(塔防类游戏)中炮塔寻怪算法有误,炮塔无法准确的找到最危险的怪物(也就是射程范围内离终点最近)。最后查看代码发现,以前怪物查询算法只需查询最危险的怪物,所以遍历所有的怪物,记录最危险那只就可以了。后来策划新增需求,炮塔需要短时间内陆续攻击最危险的N只怪。所以算法上就改成先将所有怪物排序,再取所需的怪物。因为排序有使用到两个变量排序用的 怪物剩余路程 和 怪物实例 。考虑到数组存储不方便,而且需要特别的写排序代码。想到Object是存在Key自动排序功能的,所以使用了一个Object去遍历后存储怪物(剩余路程为key,怪物实例为value)。最后事与愿违,并没有得到想要的结果。下面也就以此为例,带大家了解一下 对象(Object)的自动排序问题。
一、object的自动排序功能
我们在开发游戏的过程中常会遇到这种情况,将几个聊天频道的的聊天消息按时间顺序重新排序放到综合频道展示。或是服务器发了一堆战斗记录(不保证顺序)给我们展示。我们要快速的处理这些事情,经常会用到object的自动排序功能,下面代码做一段object的自动排序功能
var printObject = function(obj){
console.log(`printObject begin`);
var i = 0;
for(var key in obj){
console.log(`key${i} ${key}:${obj[key]}`);
i++;
}
console.log(`printObject end`);
}
var randomObject = function(num){
let numObj = {};
for(var i = 0; i<num; i++){
let numStr = Math.floor(Math.random()*3);
let randomNum = Math.floor(Math.random()*(Math.pow(10, numStr)));
console.log(`random key${i}:${randomNum}`);
numObj[randomNum] = "fdsf";
}
printObject(numObj);
return numObj;
}
二、object的自动排序测试
运行以上的随机函数结果如下:
运行: randomOjbect(5)
结果:
random key0:9
random key1:99
random key2:0
random key3:6
random key4:53
printObject begin
key0 0:fdsf
key1 6:fdsf
key2 9:fdsf
key3 53:fdsf
key4 99:fdsf
printObject end
运行: randomOjbect(5)
结果:
random key0:9
random key1:99
random key2:0
random key3:6
random key4:53
printObject begin
key0 0:fdsf
key1 6:fdsf
key2 9:fdsf
key3 53:fdsf
key4 99:fdsf
printObject end
三、Object混合属性的自动排序功能
以上两次运行结果可以发现,对象能对属性正确的自动排序,所以直觉的可以认为以number为属性的对象,都能以从小到大的顺序自动排序。但是事实真是如此吗?如果是这样,那文章一开头描述的问题又是什么情况呢?接下来我们对随机函数稍作修改,继续测试几次:
var randomObject = function(num, hasFloat){
let numObj = {};
for(var i = 0; i<num; i++){
let numStr = Math.floor(Math.random()*6);
let randomNum = Math.floor(Math.random()*(Math.pow(10, numStr)));
let numLen = randomNum.toString().length;
let dotpoint = Math.floor(Math.random()*numLen);//随机小数部分的位数
if(hasFloat && Math.floor(Math.random()*2 === 0)){
dotPoint = 0;
}
randomNum = randomNum/Math.pow(10, dotPoint); //对整数进行小数处理
console.log(`random key${i}:${randomNum}`);
numObj[randomNum] = "fdsf";
}
printObject(numObj);
return numObj;
}
四、混合自动排序测试
以上函数主要修改是,将在随机数中添加部分浮点数。这样整个属性中就有整形number,也有浮点型number。这样结果又会怎样呢?
下面一样随机允许两次看看结果
运行: randomOjbect(5, true)
结果:
random key0:7
random key1:4308
random key2:5.1
random key3:3
random key4:4.4605printObject begin
key0 3:fdsf
key1 7:fdsf
key2 4308:fdsf
key3 5.1:fdsf
key4 4.4605:fdsf
printObject end
运行: randomOjbect(5, true)
结果:
random key0:39
random key1:447.5
random key2:69
random key3:5.26
random key4:7printObject begin
key0 7:fdsf
key1 39:fdsf
key2 69:fdsf
key3 447.5:fdsf
key4 5.26:fdsf
printObject end
由上面的结果可以看出,属性排序后并不是完全由小到大的排序,其中分整数和浮点数部分,整数部分为数字大小从小到大排序。浮点数部分则并未排序,是按照放入的顺序排序。
总结
由此总结几点如下:
- JS存在自动排序机制
- 自动排序规则如下
- 整数数字属性,按从小到大排序
- 字符串属性,不进行自动排序。按照写入的顺序排序。
- 浮点型属性,按照字符串属性方式处理
- 同时存在整数数字类型和字符串类型时。优先排列整数数字类型。
下面提供 整数数字、浮点型数字、和字符串 三种属性的排序测试代码 【查看】