这篇文章主要介绍了 javascript 实现数组内值索引随机化及创建随机数组的方法, 涉及 javascript 数组索引及随机数的相关实现技巧, 具有一定参考借鉴价值, 需要的朋友可以参考下
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
本文实例讲述了 javascript 实现数组内值索引随机化及创建随机数组的方法。分享给大家供大家参考。具体如下:
今天在 QW 交流群里看到有同学讨论使数组随机化的问题,其中给出的算法很不错,让我想起了之前自己实现过的不怎么 "漂亮" 的方法。想想我们有时候在繁忙的写业务代码时只是为了实现其功能,并未花太大心思去思考是否有更好的实现方法。
就这个数组问题 (随即排序一个数组里的值,返回一个新数组) 来说,我以前的实现方法是这样的:
- function randArr(arr) {
- var ret = [],
- obj = {},
- i = arr.length,
- l = i,
- n;
- while (--i >= 0) {
- n = Math.floor( Math.random() * l );
- if (obj[n] === void 0) {
- ret[ret.length] = obj[n] = arr[n];
- } else {
- i++;
- }
- }
- return ret;
- }
上面的代码会工作,但并不是一个好的算法,它打算执行 "原数组的长度" 次循环,每一次循环会随机取一个原数组中的索引,然后判断该索引是否已被取过,如果没有则把该索引的值放入新数组中,如果取过则把自减键 i 自增 1(目的是重复该次循环直到取到另一个未取过的索引)。这样的方法的性能是很看人品的,原因相信看到这种思路的同学都已明白了。
现在给出群里那位同学的算法:
- function randArr(arr) {
- var ret = [],
- i = arr.length,
- n;
- arr = arr.slice(0);
- while (--i >= 0) {
- n = Math.floor( Math.random() * i);
- ret[ret.length] = arr.splice(n, 1)[0];
- }
- return ret;
- }
这是一个相当巧妙的算法,在每次循环中取一个随机的索引后,并把它的值从数组中删除,这样,如果后面依然随机取到这个索引,这个索引就已经不再是上一次取到的值了,而且随机数的取值范围会根据数组的长度的减小而减小,这样就能一次性循环一定的次数而得到理想的结果。
还看到了一个改进版的,是考虑到了对数组的删除操作而导致的些许性能问题,运用了 JK 大的洗牌算法,即把每一次删除操作改为了位置替换操作 (取到的该索引的值和当前自减键 i 对应的值进行互换),这样对整个数组的影响是最小的,还是放代码吧:
- function randArr(arr) {
- var ret = [],
- i = arr.length,
- n;
- arr = arr.slice(0);
- while (--i >= 0) {
- n = Math.floor( Math.random() * i);
- ret[ret.length] = arr[n];
- arr[n] = arr[i];
- }
- return ret;
- }
最后给出一个 "创建值为 min~max 间的随机数组" 的方法, 算法原理同上面的差不多:
- function makeRandArr(min, max) {
- var ret = [],
- obj = {},
- n;
- for (; max >= min; max--) {
- n = Math.ceil( Math.random() * (max - min) ) + min;
- ret[ret.length] = obj[n] || n;
- obj[n] = obj[max] || max;
- }
- return ret;
- }
希望本文所述对大家的 javascript 程序设计有所帮助。
来源: