通过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实现win8一样酷炫的动态磁贴效果(示例代码)
Jul 13 Javascript
AJAX跨域请求json数据的实现方法
Nov 11 Javascript
js父页面中使用子页面的方法
Jan 09 Javascript
详解微信小程序 wx.uploadFile 的编码坑
Jan 23 Javascript
Three.js利用orbit controls插件(轨道控制)控制模型交互动作详解
Sep 25 Javascript
详解开源的JavaScript插件化框架MinimaJS
Oct 26 Javascript
详解es6超好用的语法糖Decorator
Aug 01 Javascript
vue项目中使用lib-flexible解决移动端适配的问题解决
Aug 23 Javascript
微信小程序渲染性能调优小结
Jul 30 Javascript
微信小程序表单验证插件WxValidate的二次封装功能(终极版)
Sep 03 Javascript
微信小程序复选框实现多选一功能过程解析
Feb 14 Javascript
TS 类型兼容教程示例详解
Sep 23 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安全防护之Web攻击
2017/01/03 PHP
Add Formatted Text to a Word Document
2007/06/15 Javascript
超棒的javascript页面顶部卷动广告效果
2007/12/01 Javascript
JQuery中each()的使用方法说明
2010/08/19 Javascript
IE6下拉框图层问题探讨及解决
2014/01/03 Javascript
jQuery实现单击按钮遮罩弹出对话框(仿天猫的删除对话框)
2014/04/10 Javascript
JS制作简单的三级联动
2015/03/18 Javascript
JavaScript计算某一天是星期几的方法
2015/08/05 Javascript
使用jsonp实现跨域获取数据实例讲解
2016/12/25 Javascript
函数四种调用模式以及其中的this指向
2017/01/16 Javascript
JS获取鼠标坐标并且根据鼠标位置不同弹出不同内容
2017/06/12 Javascript
详解使用angularjs的ng-options时如何设置默认值(初始值)
2017/07/18 Javascript
解决vue.js this.$router.push无效的问题
2018/09/03 Javascript
jquery实现图片无缝滚动 蒙版遮蔽效果
2020/01/11 jQuery
基于Python的身份证号码自动生成程序
2014/08/15 Python
Python中SOAP项目的介绍及其在web开发中的应用
2015/04/14 Python
spyder常用快捷键(分享)
2017/07/19 Python
python+matplotlib绘制旋转椭圆实例代码
2018/01/12 Python
Python迭代器和生成器定义与用法示例
2018/02/10 Python
python学生信息管理系统
2018/03/13 Python
使用Python从零开始撸一个区块链
2018/03/14 Python
Python中logging.NullHandler 的使用教程
2018/11/29 Python
python 字符串常用方法汇总详解
2019/09/16 Python
Python解压 rar、zip、tar文件的方法
2019/11/19 Python
tensorflow2.0保存和恢复模型3种方法
2020/02/03 Python
Python图像处理库PIL的ImageFilter模块使用介绍
2020/02/26 Python
美国钻石商店:Zales
2016/11/20 全球购物
《从现在开始》教学反思
2014/04/15 职场文书
党的群众路线教育实践活动总结报告
2014/04/28 职场文书
法制宣传口号
2014/06/16 职场文书
公共场所禁烟标语
2014/06/25 职场文书
2015医德医风个人工作总结
2015/04/02 职场文书
小学教师岗位职责
2015/04/02 职场文书
红色经典观后感
2015/06/18 职场文书
解析laravel使用workerman用户交互、服务器交互
2021/04/28 PHP
python turtle绘制多边形和跳跃和改变速度特效
2022/03/16 Python