通过js随机函数Math.random实现乱序


Posted in Javascript onMay 19, 2020

乱序的意思想必没有不知道:就是将数组打乱。听到乱序一般都会想到js的随机函数Math.random();

var values = [1, 2, 3, 4, 5];
values.sort(function() {
  return Math.random() - 0.5;
});
console.log(values)

利用数组的sort方法,判断随机出来的0~1值与0.5的大小,实现排序。看似一个很不错的方案,代码逻辑也没毛病,一般情况下也确实能够做到乱序。但是,这是一个伪排序,是的还有但是(我也是今天才知道的,不求甚解的毛病啊~),为什么呢?先看看这个乱序的结果吧:

var times = [0, 0, 0, 0, 0];
for (var i = 0; i < 100000; i++) {
  let arr = [1, 2, 3, 4, 5];
  arr.sort(() => Math.random() - 0.5);
  times[arr[4] - 1]++;
};
console.log(times)

测试的原理是:将[1, 2, 3, 4, 5]乱序10万次,计算乱序后数组的最后一个元素是1,2,3,4,5的次数分别是多少。

运行几次得到的结果为:

通过js随机函数Math.random实现乱序通过js随机函数Math.random实现乱序通过js随机函数Math.random实现乱序

由这几次运行得到的结果可以看出:2出现的最后的次数明显少于其他数字,不是随机吗?按理说概率应该是相差不多才对啊!
其实问题是在sort方法,各个浏览器对sort的实现方式不一样。

Chrome的sort

基于V8引擎,它的排序算进行了很多的优化,但是核心是小于等于10的数组用插入排序(稳定),大于10的采用了quickSort(不稳定)

FireFox的sort

基于SpiderMonkey引擎,采用了归并排序(稳定)

Safari的sort

基于Nitro(JavaScriptCore )引擎,如果没有自定义的排序规则传入,采用桶排序(不一定稳定, 桶排序的稳定性取决于桶内排序的稳定性, 因此其稳定性不确定。),传入自定义规则,采用归并排序(稳定)

Microsoft Edge/IE9+

基于Chakra引擎,采用快排(不稳定)

以下用chrome测试乱序各种结果的概率:

var times = 100000;
var res = {};
for(var i = 0; i < times; i++){
  var arr = [1, 2, 3];
  arr.sort(() => Match.random() - 0.5);
  var key = JSON.stringify(arr);
  res[key] ? res[key]++ : res[key] = 1;
}

// 为了方便展示,转换成百分比
for (var key in res) {
  res[key] = res[key] / times * 100 + '%';
}
console.log(res);

结果如下

通过js随机函数Math.random实现乱序

几种结果出现的概率相差很大...所以说不是一个真正的乱序。

Fisher-Yates算法【也叫“洗牌算法”】:为什么叫 Fisher?Yates 呢? 因为这个算法是由 Ronald Fisher 和 Frank Yates 首次提出的。代码如下:

function shuffle(a) {
  var j, x, i;
  for (i = a.length; i; i--) {
    j = Math.floor(Math.random() * i);
    x = a[i-1];
    a[i - 1] = a[j];
    a[j] = x;
  }
  return a;
}

其原理就是:遍历数组元素,然后将当前元素与以后随机位置的元素进行交换,这样乱序更加彻底。

如果用ES6的写法还能精简成:

function shuffle(a) {
  for(let i = a.length; i; i--) {
    let j = Math.floor(Math.random() * i);
    [a[i - 1], a[j]] = [a[j], a[i - 1]];
  }
  return a;
}

再用上面的demo测试一下:

var times = 100000;
var res = {};

for (var i = 0; i < times; i++) {
  var arr = shuffle([1, 2, 3]);

  var key = JSON.stringify(arr);
  res[key] ? res[key]++ : res[key] = 1;
}

// 为了方便展示,转换成百分比
for (var key in res) {
  res[key] = res[key] / times * 100 + '%'
}

console.log(res)

得到结果如下:

通过js随机函数Math.random实现乱序

各种结果的概率都基本相同了,所以真正实现了乱序的效果!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
为JavaScript提供睡眠功能(sleep) 自编译JS引擎
Aug 16 Javascript
IE6不能修改NAME问题的解决方法
Sep 03 Javascript
jquery实现marquee效果(文字或者图片的水平垂直滚动)
Jan 07 Javascript
jquery插件开发之实现md5插件
Mar 17 Javascript
jquery 实现滚动条下拉时无限加载的简单实例
Jun 01 Javascript
基于JS脚本语言的基础语法详解
Jul 22 Javascript
vue.js项目nginx部署教程
Apr 05 Javascript
Bootstrap table中toolbar新增条件查询及refresh参数使用方法
May 18 Javascript
详解React中合并单元格的正确写法
Jan 08 Javascript
微信小程序实现购物车代码实例详解
Aug 29 Javascript
Vue学习之组件用法实例详解
Jan 06 Javascript
Vue快速实现通用表单验证的方法
Feb 24 Javascript
javascript实现获取中文汉字拼音首字母
May 19 #Javascript
微信小程序实现菜单左右联动
May 19 #Javascript
JS array数组检测方式解析
May 19 #Javascript
基于JS实现table导出Excel并保留样式
May 19 #Javascript
vue利用全局导航守卫作登录后跳转到未登录前指定页面的实例代码
May 19 #Javascript
jQuery 函数实例分析【函数声明、函数表达式、匿名函数等】
May 19 #jQuery
JS加载解析Markdown文档过程详解
May 19 #Javascript
You might like
PHP 变量的定义方法
2010/01/26 PHP
PHP 图片上传实现代码 带详细注释
2010/04/29 PHP
使用bcompiler对PHP文件进行加密的代码
2010/08/29 PHP
php使HTML标签自动补全闭合函数代码
2012/10/04 PHP
php自定义函数截取汉字长度
2014/05/15 PHP
ThinkPHP中order()使用方法详解
2016/04/19 PHP
PHP对称加密函数实现数据的加密解密
2016/10/27 PHP
Laravel5中Cookie的使用详解
2017/05/03 PHP
Tab页界面,用jQuery及Ajax技术实现
2009/09/21 Javascript
在IE和VB中支持png图片透明效果的实现方法(vb源码打包)
2011/04/01 Javascript
js获取单选框或复选框值及操作
2012/12/18 Javascript
js禁止回车提交表单的示例代码
2013/12/23 Javascript
js判断浏览器是否支持html5
2014/08/17 Javascript
javascript实现点击后变换按钮显示文字的方法
2015/05/13 Javascript
js+html5操作sqlite数据库的方法
2016/02/02 Javascript
AngularJs 指令详解及示例代码
2016/09/01 Javascript
React-Native使用Mobx实现购物车功能
2017/09/14 Javascript
Angular js 实现添加用户、修改密码、敏感字、下拉菜单的综合操作方法
2017/10/24 Javascript
详解搭建es6+devServer简单开发环境
2018/09/25 Javascript
深入解析koa之异步回调处理
2019/06/17 Javascript
jquery实现自定义树形表格的方法【自定义树形结构table】
2019/07/12 jQuery
Javascript基于OOP实实现探测器功能代码实例
2020/08/26 Javascript
使用python实现个性化词云的方法
2017/06/16 Python
修改默认的pip版本为对应python2.7的方法
2018/11/06 Python
PyQt5图形界面播放音乐的实例
2019/06/17 Python
在django中实现choices字段获取对应字段值
2020/07/12 Python
CSS3实现文字描边的2种方法(小结)
2020/02/14 HTML / CSS
Revolution Beauty美国官网:英国知名化妆品网站
2018/07/23 全球购物
坚守艰苦奋斗精神坚决反对享乐主义整改措施
2014/09/17 职场文书
公司领导班子群众路线四风问题对照检查材料
2014/10/02 职场文书
学校政风行风整改方案
2014/10/25 职场文书
介绍信范文大全
2015/05/07 职场文书
销售合作意向书范本
2015/05/08 职场文书
2016年小学圣诞节活动总结
2016/03/31 职场文书
Python OpenCV快速入门教程
2021/04/17 Python
浅谈 JavaScript 沙箱Sandbox
2021/11/02 Javascript