我有一个这样的数组:

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

我如何随机化/打乱它?


当前回答

使用生成器功能的ES6压缩代码*

这是通过从未屏蔽阵列的副本中随机移除项目,直到没有剩余项目。它使用新的ES6生成器功能。

设arr=[1,2,3,4,5,6,7]函数*洗牌(arr){arr=[…arr];而(arr.length)产生arr.splice(Math.random()*arr.length|0,1)[0]}console.log([…shuffle(arr)])

或者,使用ES6和拼接:

设arr=[1,2,3,4,5,6,7]let shuffled=arr.reduce(([a,b])=>(b.push(…a.splice(Math.random()*a.length |0,1)),[a,b]),[[…arr],[]])[1]console.log(混洗)

或者,ES6索引交换方法:

设arr=[1,2,3,4,5,6,7]let shuffled=arr.reduce((a,c,i,r,j)=>(j=数学随机()*(a.length-i)|0,[a[i],a[j]]=[a[j],a[i]],a),[…arr])console.log(混洗)

其他回答

编辑:此答案不正确

参见评论和https://stackoverflow.com/a/18650169/28234.这里留作参考,因为这种想法并不罕见。


对于小型阵列,一个非常简单的方法就是:

const someArray = [1, 2, 3, 4, 5];

someArray.sort(() => Math.random() - 0.5);

它可能效率不高,但对于小型阵列来说,这很好。这里有一个例子,你可以看到它有多随机(或不随机),以及它是否适合你的用例。

const resultsEl=document.querySelector(“#results”);const buttonEl=document.querySelector(“#trigger”);常量生成器数组和随机化=()=>{常量someArray=[0,1,2,3,4,5,6,7,8,9];someArray.sort(()=>Math.random()-0.5);return someArray;};const renderResultsToDom=(结果,el)=>{el.innerHTML=results.join(“”);};buttonEl.addEventListener('click',()=>renderResultsToDom(generateArray AndRandomize(),resultsEl));<h1>随机化</h1><button id=“trigger”>生成</button><p id=“results”>0 1 2 3 4 5 6 7 8 9</p>

不改变源数组的shuffle函数

更新:这里我建议使用一种相对简单(不是从复杂性角度)和较短的算法,它可以很好地处理小型阵列,但在处理大型阵列时,它的成本肯定要比经典的Durstenfeld算法高得多。你可以在对这个问题的回答中找到杜斯滕菲尔德。

原答覆:

如果您不希望shuffle函数改变源数组,可以将其复制到本地变量,然后使用简单的shuffle逻辑完成其余操作。

function shuffle(array) {
  var result = [], source = array.concat([]);

  while (source.length) {
    let index = Math.floor(Math.random() * source.length);
    result.push(source[index]);
    source.splice(index, 1);
  }

  return result;
}

疏解逻辑:选取一个随机索引,然后将相应的元素添加到结果数组中,然后从源数组副本中删除它。重复此操作,直到源阵列变为空。

如果你真的想要简短的话,下面是我能做到的程度:

function shuffle(array) {
  var result = [], source = array.concat([]);

  while (source.length) {
    let index = Math.floor(Math.random() * source.length);
    result.push(source.splice(index, 1)[0]);
  }

  return result;
}

事实上的无偏洗牌算法是Fisher Yates(又名Knuth)shuffle。

你可以在这里看到一个很棒的可视化效果(以及链接到此的原始帖子)

函数洗牌(数组){let currentIndex=array.length,randomIndex;//而还有一些元素需要洗牌。while(currentIndex!=0){//拾取剩余的元素。randomIndex=数学地板(Math.random()*当前索引);当前索引--;//并将其与当前元素交换。[array[currentIndex],array[randomIndex]]=[array[randomIndex],array[currentIndex]];}返回数组;}//如此使用var arr=[2,11,37,42];洗牌(arr);控制台日志(arr);

有关所用算法的更多信息。

费希尔·耶茨在javascript中洗牌。我在这里发表这篇文章是因为与这里的其他答案相比,使用两个实用函数(swap和randInt)澄清了算法。

function swap(arr, i, j) { 
  // swaps two elements of an array in place
  var temp = arr[i];
  arr[i] = arr[j];
  arr[j] = temp;
}
function randInt(max) { 
  // returns random integer between 0 and max-1 inclusive.
  return Math.floor(Math.random()*max);
}
function shuffle(arr) {
  // For each slot in the array (starting at the end), 
  // pick an element randomly from the unplaced elements and
  // place it in the slot, exchanging places with the 
  // element in the slot. 
  for(var slot = arr.length - 1; slot > 0; slot--){
    var element = randInt(slot+1);
    swap(arr, element, slot);
  }
}

使用array.splice()随机化数组

function shuffleArray(array) {
   var temp = [];
   var len=array.length;
   while(len){
      temp.push(array.splice(Math.floor(Math.random()*array.length),1)[0]);
      len--;
   }
   return temp;
}
//console.log("Here >>> "+shuffleArray([4,2,3,5,8,1,0]));

demo