javascript随机打乱数组shuffle

版权声明:本文为博主原创文章,未经博主允许不得转载。 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

猜你喜欢

转载自blog.csdn.net/wulove52/article/details/85804728