JavaScript学习笔记之数组随机排序


Posted in Javascript onMarch 23, 2016

推荐阅读:JavaScript学习笔记之数组求和方法

JavaScript中提供了sort()和reverse()方法对数组项重新排序。但很多时候这两个方法无法满足我们实际业务的需求,比如说扑克牌游戏中的随机洗牌。

JavaScript学习笔记之数组随机排序

在这篇文章一起来学习如何完成上面这个示例的效果,以及一些有关于数组随机排序的相关知识。

在网上查了一下有关于数组随机排序的相关资料,都看到了Math.random()的身影。打开浏览器控制器,输入:

Math.random()

JavaScript学习笔记之数组随机排序

从图中可以看出Math.random()得到的是0~1之间的随机数。众所周知,sort()可以调用一个函数做为参数,如果这个函数返回的值为-1表示数组中的a项排在b项前。如此一来,可以写一个随机函数,让Math.random()随机出来的数与0.5做为一个比较,如果大于.5就返回 -1(a排在b前面),反之返回1(b排在a前面):

function randomSort(a, b) {
return Math.random() > 0.5 ? -1 : 1;
}

看个示例:

var arr = [1,2,3,4,5,6,7,8,9];
arr.sort(randomSort);

JavaScript学习笔记之数组随机排序

这样一来,就可以实现文章开头的示例效果:

虽然前面的方法实现了数组的随机排序,但总感觉每个元素被派到新数组的位置不是随机的。就如前面的示例,数组arr中值为1的元素,它的原先键值为0,随机排序后,1的键值要求上为0-8的几率是一样的。然后在这里是递减的,原因是sort()方法是依次比较的。

针对这种现象,我们可以使用下面这种递归的方法来处理:

function randomSort(arr, newArr) {
// 如果原数组arr的length值等于1时,原数组只有一个值,其键值为0
// 同时将这个值push到新数组newArr中
if(arr.length == 1) {
newArr.push(arr[0]);
return newArr; // 相当于递归退出
}
// 在原数组length基础上取出一个随机数
var random = Math.ceil(Math.random() * arr.length) - 1;
// 将原数组中的随机一个值push到新数组newArr中
newArr.push(arr[random]);
// 对应删除原数组arr的对应数组项
arr.splice(random,1);
return randomSort(arr, newArr);
}

如此一来,我们就可以这样使用:

for (var i = 0; i < 10; i++) {
var arr=[1,2,3,4,5,6,7,8,9];
var newArr=[];
randomSort(arr,newArr);
console.log(newArr);
}

输出结果:

JavaScript学习笔记之数组随机排序

执行randomSort(arr,newArr)函数之后,原数组arr就清空了。

如果使用这种方法来做文章开头洗牌的示例,就要在resetPic()函数中重置pukePic数组:

除了上面的两种方法之外,@Traveller在DIV.IO分享了一篇《数组元素随机化排序算法实现》,这篇文章提供了三种数组项随机排序的实现方法:

使用数组sort方法对数组元素随机排序

Array.prototype.shuffle = function(n) {
var len = this.length ,
num = n ? Math.min(n,len) : len,
arr = this.slice(0);
arr.sort(function(a,b){
return Math.random()-0.5;
});
return arr.slice(0,num-1);
}

随机交换数组内的元素

lib = {}
lib.range = function(min,max) {
return min + Math.floor(Math.random()*(max-min+1));
}

Array.prototype.shuffle = function(n) {
var len = this.length,
num = n ? Math.min(n,len) : len,
arr = this.slice(0),
temp,
index;
for (var i=0;i<len;i++){
index = lib.range(i,len-1);
temp = arr[i];
arr[i] = arr[index];
arr[index]=temp;
}
return arr.slice(0,num);
}

随机从原数组抽取一个元素,加入到新数组

lib = {}
lib.range = function(min,max) {
return min+Math.floor(Math.random()*(max-min+1));
}
Array.prototype.shuffle = function(n) {
var len = this.length, 
num = n ? Math.min(n,len) : len,
arr = this.slice(0),
result=[],
index;
for (var i=0;i<num;i++){
index = lib.range(0,len-1-i);
// 或者 result.concat(arr.splice(index,1))
result.push(arr.splice(index,1)[0]);
}
return result
}

洗牌算法

数组随机排序其基本原理是洗牌算法(Fisher?Yates shuffle):

是一种将有限集合的顺序打乱的一种算法

原理

定义一个数组(shuffled),长度(length)是原数组(arr)长度
取 0 到 index (初始0) 随机值 rand, shuffled[index] = shuffled[rand], shuffled[rand] = arr[index]
index++ ; 重复第二步,直到 index = length -1
就是 shuffled 从 0 到 length-1 的赋值过程,并且新加入的值是 arr[index],shuffled[index] 的值是已赋值的元素中随机值shuffled[rand],因为这样会有两个重复的值,所以 shuffled[rand] 就等于新加入的值 arr[index]

underscore.js 中的 shuffle 方法

function random(min, max) {
if (max == null) {
max = min;
min = 0;
}
return min + Math.floor(Math.random() * (max - min + 1));
};
function shuffle(arr) {
var length = arr.length,
shuffled = Array(length);
for (var index = 0, rand; index < length; index++) {
rand = random(0, index);
if (rand !== index) shuffled[index] = shuffled[rand];
shuffled[rand] = arr[index];
}
return shuffled;
}

实际运用:

var arr = [1,2,3,4,5,6,7,8,9];
for (var i = 0; i < 10; i++){
console.log(shuffle(arr));
}

Chrome输出的结果如下:

JavaScript学习笔记之数组随机排序

同样的,使用洗牌算法来完成文章最开头的示例:

JavaScript学习笔记之数组随机排序

还有更简单易理解的写法:

function shuffle(arr) {
var i, 
j,
temp;
for (i = arr.length - 1; i > 0; i--) {
j = Math.floor(Math.random() * (i + 1));
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;
};

总结

这篇文章主要总结和收集了有关于数组随机排序我相关资料。当然在坊间实现类似功能的方法还有很多种,此处只是收集和整理了这些,如果你有更好的方法,欢迎在评论中与我们一起分享。

以上内容是小编给大家介绍的JavaScript学习笔记之数组随机排序的相关介绍,希望对大家有所帮助!

Javascript 相关文章推荐
javascript学习笔记(八) js内置对象
Jun 19 Javascript
jquery插件制作 提示框插件实现代码
Aug 17 Javascript
JS 获取滚动条高度示例代码
Oct 24 Javascript
在百度知道团队中快速审批新成员的js脚本
Feb 02 Javascript
jquery和雅虎的yql服务实现天气预报服务示例
Feb 08 Javascript
JS如何判断是否为ie浏览器的方法(包括IE10、IE11在内)
Dec 13 Javascript
JQuery手速测试小游戏实现思路详解
Sep 20 Javascript
详解Angular.js中$http拦截器的介绍及使用
Jul 04 Javascript
JS库particles.js创建超炫背景粒子插件(附源码下载)
Sep 13 Javascript
React中如何引入Angular组件详解
Aug 09 Javascript
Vue的v-model的几种修饰符.lazy,.number和.trim的用法说明
Aug 05 Javascript
Vue.js 带下拉选项的输入框(Textbox with Dropdown)组件
Apr 17 Vue.js
JavaScript学习笔记之数组求和方法
Mar 23 #Javascript
JavaScript学习笔记之数组的增、删、改、查
Mar 23 #Javascript
高效利用Angular中内置服务$http、$location等
Mar 22 #Javascript
BootStrap实用代码片段之一
Mar 22 #Javascript
Javascript中的几种继承方式对比分析
Mar 22 #Javascript
JS函数定义方式的区别介绍
Mar 22 #Javascript
基于javascript制作经典传统的拼图游戏
Mar 22 #Javascript
You might like
简单的用PHP编写的导航条程序
2006/10/09 PHP
PHP 页面编码声明方法详解(header或meta)
2010/03/12 PHP
Zend Framework动作助手Redirector用法实例详解
2016/03/05 PHP
PHP实现的基于单向链表解决约瑟夫环问题示例
2017/09/30 PHP
PHP实现给定一列字符,生成指定长度的所有可能组合示例
2019/06/22 PHP
PHP设计模式(九)外观模式Facade实例详解【结构型】
2020/05/02 PHP
jQuery实现长文字部分显示代码
2013/05/13 Javascript
confirm的用法示例用于按钮操作时确定是否执行
2014/06/19 Javascript
JavaScript实现仿新浪微博大厅和腾讯微博首页滚动特效源码
2015/09/15 Javascript
JavaScript File API实现文件上传预览
2016/02/02 Javascript
vue-cli+webpack记事本项目创建
2017/04/01 Javascript
详细介绍RxJS在Angular中的应用
2017/09/23 Javascript
详解刷新页面vuex数据不消失和不跳转页面的解决
2018/01/30 Javascript
用Electron写个带界面的nodejs爬虫的实现方法
2019/01/29 NodeJs
JavaScript如何把两个数组对象合并过程解析
2019/10/10 Javascript
JavaScript图片旋转效果实现方法详解
2020/06/28 Javascript
[00:09]DOTA2新版本PA至宝特效动作展示
2014/11/19 DOTA
Python线性方程组求解运算示例
2018/01/17 Python
Python使用cx_Oracle模块操作Oracle数据库详解
2018/05/07 Python
Python不使用int()函数把字符串转换为数字的方法
2018/07/09 Python
Python3 执行系统命令并获取实时回显功能
2019/07/09 Python
Python 线程池用法简单示例
2019/10/02 Python
Python如何将图像音视频等资源文件隐藏在代码中(小技巧)
2020/02/16 Python
CSS3 中的@keyframes介绍
2014/09/02 HTML / CSS
深入了解canvas在移动端绘制模糊的问题解决
2019/04/30 HTML / CSS
King Apparel官网:英国街头服饰品牌
2019/09/05 全球购物
公务员个人自我评价分享
2013/11/06 职场文书
新闻学专业应届生求职信
2013/11/08 职场文书
中专毕业生的自我鉴定
2013/12/01 职场文书
幼儿园中秋节活动反思
2014/02/16 职场文书
小学数学课后反思
2014/04/23 职场文书
个人遵守党的政治纪律情况对照检查材料
2014/09/26 职场文书
2014年党支部书记工作总结
2014/12/04 职场文书
学校证明范文
2015/06/24 职场文书
初中生物教学随笔
2015/08/15 职场文书
《地。-关于地球的运动-》单行本第七集上市,小说家朝井辽献上期待又害怕的推荐文
2022/03/31 日漫