JavaScript 开辟中有时会碰到要将一个数组随机排序(shuffle)的需求,一个常见的写法是如许:
- function shuffle(arr) {
- arr.sort(function () {
- return Math.random() - 0.5;
- });
- }
或者应用更简洁的 ES6 的写法:
如不雅排序真的是随机的,那么每个元素在每个地位出现的概率都应当一样,实验结不雅各个地位的数字应当很接近,而不该像如今如许明显地集中在本来地位邻近。是以,我们可以认为,应用形如arr.sort(() => Math.random() - 0.5)如许的办法获得的并不是真正的随机排序。
我也曾经经常应用这种写法,不久前才意识到,这种写法是有问题的,它并不克不及真正地随机打乱数组。
问题
看下面的代码,我们生成一个长度为 10 的数组['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],应用膳绫擎的办法将数组乱序,履行多次后,会发明每个元素仍然有很大年夜机率在它本来的地位邻近出现。
计整洁
- let n = 10000;
- let count = (new Array(10)).fill(0);
- for (let i = 0; i < n; i ++) {
- let arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'];
- arr.sort(() => Math.random() - 0.5);
- count[arr.indexOf('a')]++;
- }
- console.log(count);
在 Node.JS 6 中履行,输出[ 2891, 2928, 1927, 1125, 579, 270, 151, 76, 34, 19 ](带有必定随机性,每次结不雅都不合,但大年夜致分布应当一致),即进行 10000 次排序后,字母'a'(数组中的第一个元素)有约 2891 次涌如今第一个地位、2928 次涌如今第二个地位,与之对应的只有 19 次涌如今最后一个地位。如不雅把这个分布绘制成图像,会是下面如许:
类似地,我们可以算出字母'f'(数组中的第六个元素)在各个地位出现的分布为[ 312, 294, 579, 1012, 1781, 2232, 1758, 1129, 586, 317 ],图像如下:
如不雅要将数组随机排序,切切不要再用(a, b) => Math.random() - 0.5如许的办法。今朝而言,Fisher–Yates shuffle 算法应当是最好的选择。
别的,须要留意的是膳绫擎的分构造实用于数组长度不跨越 10 的情况,如不雅数组更长,比如长度为 11,则会是另一种分布。比如:
- let a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'
推荐阅读
由大年夜数据触发的数据驱动的做法是一种最好的懂得。如今,各个组织正在各类数据构造,格局和分布式地舆数据源地位等方面进行竞争,并在时光框架和数量上跨越了现有体系的才能。以往人们>>>详细阅读
本文标题:关于JavaScript的数组随机排序
地址:http://www.17bianji.com/lsqh/34614.html
1/2 1