版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wulove52/article/details/85804728
javascript 没有为我们提供shuffle打乱数组的函数,那日常开发是怎样实现随机打乱数组呢
一.使用sort方法?
借助 sort 方法不是真正意义上的完全乱序
原因:
在Chrome v8引擎源码中,处理 sort 方法时,使用了插入排序和快排两种方案。当目标数组长度小于10时,使用插入排序;反之,使用快排。
其实不管用什么排序方法,大多数排序算法的时间复杂度介于 O(n) 到 O(n2) 之间,元素之间的比较次数通常情况下要远小于 n(n-1)/2,也就意味着有一些元素之间根本就没机会相比较(也就没有了随机交换的可能),这些 sort 随机排序的算法自然也不能真正随机。
通俗的说,其实我们使用 array.sort 进行乱序,理想的方案或者说纯乱序的方案是:数组中每两个元素都要进行比较,这个比较有 50% 的交换位置概率。如此一来,总共比较次数一定为 n(n-1)。
而在 sort 排序算法中,大多数情况都不会满足这样的条件。因而当然不是完全随机的结果了。
某些场景下,这样的方法可以使用。但是这不是真正意义上的完全乱序,一些需求中(比如抽奖)这样的写法会出大问题。
var arr = ['A','B','C','D','F'];
var brr = [1,2,3,4,5,6,7,8];
var arr1 = arr.sort(function() {
return .5 - Math.random();
});
var brr1 = brr.sort(function() {
return .5 - Math.random();
});
console.log(arr1);
console.log(brr1);
二.Fisher–Yates shuffle 洗牌算法
Fisher–Yates shuffle 洗牌算法可以做到理论上的完全乱序
lodash.js 中的 shuffle 函数也使用此算法实现
function shuffleSelf(array, size) {
var index = -1,
length = array.length,
lastIndex = length - 1;
size = size === undefined ? length : size;
while (++index < size) {
// var rand = baseRandom(index, lastIndex),
var rand = index + Math.floor( Math.random() * (lastIndex - index + 1))
value = array[rand];
array[rand] = array[index];
array[index] = value;
}
array.length = size;
return array;
}
参考链接:
https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
https://raw.githubusercontent.com/lodash/lodash/4.17.5/dist/lodash.js