我有一个这样的数组:

var arr1 = ["a", "b", "c", "d"];

我如何随机化/打乱它?


当前回答

罗纳德·费舍尔和弗兰克·耶茨洗牌

ES2015(ES6)版本

Array.prototype.shuffle2 = function () {
    this.forEach(
        function (v, i, a) {
            let j = Math.floor(Math.random() * (i + 1));
            [a[i], a[j]] = [a[j], a[i]];
        }
    );
    return this;
}

Jet优化ES2015(ES6)版本

Array.prototype.shuffle3 = function () {
    var m = this.length;
    while (m) {
        let i = Math.floor(Math.random() * m--);
        [this[m], this[i]] = [this[i], this[m]];
    }
    return this;
}

其他回答

函数shuffleArray(数组){//在参数中创建具有给定数组长度的新数组const newArray=array.map(()=>null);//创建一个新数组,其中每个索引都包含索引值const arrayReference=array.map((项,索引)=>索引);//对参数中给定的数组进行迭代array.forEach(随机化);return newArray;函数随机化(项){const randomIndex=getRandomIndex();//替换新数组中的值newArray[arrayReference[randomIndex]]=项;//在数组引用中删除使用的索引arrayReference拼接(randomIndex,1);}//返回介于0和当前数组引用长度之间的数字函数getRandomIndex(){常量最小值=0;const max=arrayReference.length;return Math.floor(Math.random()*(max-min))+min;}}控制台日志(shuffleArray([10,20,30,40,60,70,80,90100]);

重建整个阵列,逐个将每个元素放在一个随机位置。

[1,2,3].reduce((a,x,i)=>{a.splice(Math.floor(Math.random()*(i+1)),0,x);return a},[])

变量ia=[1,2,3];var it=1000;var f=(a,x,i)=>{a.splice(Math.floor(Math.random()*(i+1)),0,x);返回a};var a=新数组(it).fill(ia).map(x=>x.reduce(f,[]));var r=新数组(ia.length).fill(0).map((x,i)=>a.reduce((i2,x2)=>x2[i]+i2,0)/it)console.log(“这些值应该相当相等:”,r);

这是最简单的一个,

function shuffle(array) {
  return array.sort(() => Math.random() - 0.5);
}

例如,您可以在此处查看

这是一个Durstenfeld shuffle的JavaScript实现,这是Fisher Yates的优化版本:

/* Randomize array in-place using Durstenfeld shuffle algorithm */
function shuffleArray(array) {
    for (var i = array.length - 1; i > 0; i--) {
        var j = Math.floor(Math.random() * (i + 1));
        var temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}

它为每个原始数组元素选择一个随机元素,并将其排除在下一次抽奖中,就像从一副牌中随机选择一样。

这种巧妙的排除将拾取的元素与当前元素交换,然后从剩余元素中拾取下一个随机元素,向后循环以获得最佳效率,确保简化随机拾取(始终可以从0开始),从而跳过最终元素。

算法运行时间为O(n)。请注意,洗牌是在适当的位置完成的,因此如果您不想修改原始数组,请首先使用.sslice(0)复制它。


编辑:更新至ES6/ECMAScript 2015

新的ES6允许我们一次分配两个变量。当我们想要交换两个变量的值时,这特别方便,因为我们可以在一行代码中完成。下面是使用此功能的同一函数的简短形式。

function shuffleArray(array) {
    for (let i = array.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [array[i], array[j]] = [array[j], array[i]];
    }
}

可以(但不应该)将其用作Array中的原型:

来自ChristopheD:

Array.prototype.shuffle = function() {
  var i = this.length, j, temp;
  if ( i == 0 ) return this;
  while ( --i ) {
     j = Math.floor( Math.random() * ( i + 1 ) );
     temp = this[i];
     this[i] = this[j];
     this[j] = temp;
  }
  return this;
}