我有一个这样的数组:

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

我如何随机化/打乱它?


当前回答

这是一个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原型的情况下连接起来的解决方案(这是一个糟糕的做法)。使用稍微鲜为人知的reduce(),我们可以轻松地以允许串联的方式进行混洗:

var randomsquares = [1, 2, 3, 4, 5, 6, 7].reduce(shuffle).map(n => n*n);

您可能希望传递第二个参数[],否则如果尝试在空数组上执行此操作,则会失败:

// Both work. The second one wouldn't have worked as the one above
var randomsquares = [1, 2, 3, 4, 5, 6, 7].reduce(shuffle, []).map(n => n*n);
var randomsquares = [].reduce(shuffle, []).map(n => n*n);

让我们将shuffle定义为:

var shuffle = (rand, one, i, orig) => {
  if (i !== 1) return rand;  // Randomize it only once (arr.length > 1)

  // You could use here other random algorithm if you wanted
  for (let i = orig.length; i; i--) {
    let j = Math.floor(Math.random() * i);
    [orig[i - 1], orig[j]] = [orig[j], orig[i - 1]];
  }

  return orig;
}

您可以在JSFiddle或此处看到它的实际应用:

var shuffle=(all,one,i,orig)=>{如果(i!==1)返回全部;//你可以在这里使用其他随机算法for(设i=原始长度;i;i-){设j=数学地板(Math.random()*i);[原始[i-1],原始[j]]=[原始[j],原始[i-1]];}返回原点;}对于(变量i=0;i<5;i++){var randomarray=[1,2,3,4,5,6,7]。reduce(shuffle,[]);console.log(JSON.stringify(randomarray));}

Fisher Yates的这种变体稍微更有效,因为它避免了元素与自身的交换:

function shuffle(array) {
  var elementsRemaining = array.length, temp, randomIndex;
  while (elementsRemaining > 1) {
    randomIndex = Math.floor(Math.random() * elementsRemaining--);
    if (randomIndex != elementsRemaining) {
      temp = array[elementsRemaining];
      array[elementsRemaining] = array[randomIndex];
      array[randomIndex] = temp;
    }
  }
  return array;
}

最短的arrayShuffle函数

function arrayShuffle(o) {
    for(var j, x, i = o.length; i; j = parseInt(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x);
    return o;
}

随机化数组

 var arr = ['apple','cat','Adam','123','Zorro','petunia']; 
 var n = arr.length; var tempArr = [];

 for ( var i = 0; i < n-1; i++ ) {

    // The following line removes one random element from arr 
     // and pushes it onto tempArr 
     tempArr.push(arr.splice(Math.floor(Math.random()*arr.length),1)[0]);
 }

 // Push the remaining item onto tempArr 
 tempArr.push(arr[0]); 
 arr=tempArr;