通过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 相关文章推荐
基于jQuery中对数组进行操作的方法
Apr 16 Javascript
js将控件隐藏及display属性的使用介绍
Dec 30 Javascript
字段太多jquey快速清空表单内容方法
Aug 21 Javascript
js实现鼠标点击左上角滑动菜单效果代码
Sep 06 Javascript
JS控制弹出悬浮窗口(一览画面)的实例代码
May 30 Javascript
JS HTML5拖拽上传图片预览
Jul 18 Javascript
node.js中 stream使用教程
Aug 28 Javascript
微信小程序 scroll-view实现上拉加载与下拉刷新的实例
Jan 21 Javascript
JS 判断某变量是否为某数组中的一个值的3种方法(总结)
Jul 10 Javascript
vue2中的keep-alive使用总结及注意事项
Dec 21 Javascript
javascript中toFixed()四舍五入使用方法详解
Sep 28 Javascript
node 解析图片二维码的内容代码实例
Sep 11 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的FTP学习(二)[转自奥索]
2006/10/09 PHP
PHP 如何获取二维数组中某个key的集合
2014/06/03 PHP
PHP在innodb引擎下快速代建全文搜索功能简明教程【基于xunsearch】
2016/10/14 PHP
PHP调试及性能分析工具Xdebug详解
2017/02/09 PHP
使用Rancher在K8S上部署高性能PHP应用程序的教程
2020/07/10 PHP
AJAX使用了UpdatePanel后无法使用alert弹出脚本
2010/04/02 Javascript
从盛大通行证上摘下来的身份证验证js代码
2011/01/11 Javascript
javascript 基础篇4 window对象,DOM
2012/03/14 Javascript
JS在IE下缺少标识符的错误
2014/07/23 Javascript
使用纯javascript实现放大镜效果
2015/03/18 Javascript
javascript实现的图片切割多块效果实例
2015/05/07 Javascript
Bootstrap每天必学之导航条
2015/11/27 Javascript
jQuery validate+artdialog+jquery form实现弹出表单思路详解
2016/04/18 Javascript
工作中比较实用的JavaScript验证和数据处理的干货(经典)
2016/08/03 Javascript
js字符串操作总结(必看篇)
2016/11/22 Javascript
Bootstrap基本组件学习笔记之列表组(11)
2016/12/07 Javascript
zTree实现节点修改的实时刷新功能
2017/03/20 Javascript
微信小程序实现上拉加载功能示例【加载更多数据/触底加载/点击加载更多数据】
2020/05/29 Javascript
python3 打开外部程序及关闭的示例
2018/11/06 Python
浅谈python写入大量文件的问题
2018/11/09 Python
Python+pyplot绘制带文本标注的柱状图方法
2019/07/08 Python
利用keras加载训练好的.H5文件,并实现预测图片
2020/01/24 Python
CSS3 3D立方体效果示例-transform也不过如此
2016/12/05 HTML / CSS
使用css实现android系统的loading加载动画
2019/07/25 HTML / CSS
台湾全方位线上课程与职能学习平台:TibaMe
2019/12/04 全球购物
公司离职证明范本
2014/01/13 职场文书
《油菜花开了》教学反思
2014/02/22 职场文书
简历里的自我评价范文
2014/02/24 职场文书
生日宴会策划方案
2014/06/03 职场文书
奥林匹克运动会口号
2014/06/19 职场文书
自查自纠工作情况报告
2014/10/29 职场文书
学习雷锋精神倡议书
2015/04/27 职场文书
公司财务管理制度
2015/08/04 职场文书
小学科学课教学反思
2016/02/23 职场文书
再也不用花钱买漫画!Python爬取某漫画的脚本及源码
2021/06/09 Python
【海涛教你打DOTA】黑鸟第一视角解说
2022/04/01 DOTA