# JavaScript专题之乱序

JavaScript 专题系列第十九篇，讲解数组乱序，重点探究 Math.random() 为什么不能真正的乱序？

## Math.random

``````var values = [1, 2, 3, 4, 5];

values.sort(function(){
return Math.random() - 0.5;
});

console.log(values)``````

`Math.random() - 0.5` 随机得到一个正数、负数或是 0，如果是正数则降序排列，如果是负数则升序排列，如果是 0 就不变，然后不断的升序或者降序，最终得到一个乱序的数组。

``````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)``````

``[30636, 30906, 20456, 11743, 6259]``

## 插入排序

``````function InsertionSort(a, from, to) {
for (var i = from + 1; i < to; i++) {
var element = a[i];
for (var j = i - 1; j >= from; j--) {
var tmp = a[j];
var order = comparefn(tmp, element);
if (order > 0) {
a[j + 1] = tmp;
} else {
break;
}
}
a[j + 1] = element;
}
};``````

## 具体分析

``````var values = [1, 2, 3];

values.sort(function(){
return Math.random() - 0.5;
});``````

[1, 2, 3] 50% [1, 2, 3] 50% [1, 2, 3] 25% [1, 2, 3]
25% [1, 3, 2] 12.5% [1, 3, 2]
25% [3, 1, 2] 12.5% [3, 1, 2]
50% [2, 1, 3] 50% [2, 1, 3] 25% [2, 1, 3]
25% [2, 3, 1] 12.5% [2, 3, 1]
25% [3, 2, 1] 12.5% [3, 2, 1]

``````var times = 100000;
var res = {};

for (var i = 0; i < times; i++) {

var arr = [1, 2, 3];
arr.sort(() => Math.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)``````

## Fisher–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;
}``````

``````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;
}``````

``````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)``````

## 专题系列

JavaScript专题系列目录地址：https://github.com/mqyqingfeng/Blog

JavaScript专题系列预计写二十篇左右，主要研究日常开发中一些功能点的实现，比如防抖、节流、去重、类型判断、拷贝、最值、扁平、柯里、递归、乱序、排序等，特点是研(chao)究(xi) underscore 和 jQuery 的实现方式。

#### 你可能感兴趣的

8 条评论
FEWY · 2017年11月27日

+1 回复

KingMario · 2017年11月29日

``````var times = 100000;
var res = {};

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

arr.forEach(item=>{
arrX[item] = Math.random()
})

arr.sort((a, b)=>arrX[a] - arrX[b]);

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

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

console.table(res)``````

+1 回复

0

KingMario · 2017年12月01日
0

0

@冴羽 因为 arrX 一旦生成，arr 的顺序也就确定了，具体原理我也说不上来，直觉吧

KingMario · 2017年12月01日
KingMario · 2017年11月29日