我有一个这样的数组:

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

我如何随机化/打乱它?


当前回答

添加到@Laurens Holsts的答案。这是50%的压缩。

function shuffleArray(d) {
  for (var c = d.length - 1; c > 0; c--) {
    var b = Math.floor(Math.random() * (c + 1));
    var a = d[c];
    d[c] = d[b];
    d[b] = a;
  }
  return d
};

其他回答

您可以通过以下方式轻松完成:

//阵列var fruits=[“香蕉”、“橙色”、“苹果”、“芒果”];//随机的,随机的fruits.sort(函数(a,b){return 0.5-Math.random()});//输出console.log(水果);

请参考JavaScript排序数组

不改变源数组的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 shuffle的递归实现(我认为)。它给出了统一的随机性。

注意:~~(双颚化符运算符)实际上与正实数的Math.floor()类似。这只是一条捷径。

var shuffle=a=>a.length?a.splice(~~(Math.random()*a.length),1).contat(shuffle(a)):a;console.log(JSON.stringify(shuffle([0,1,2,3,4,5,6,7,8,9]));

编辑:由于使用了.splice(),上面的代码是O(n^2),但我们可以通过交换技巧消除O(n)中的拼接和混洗。

var shuffle=(a,l=a.length,r=~~(Math.random()*l))=>l?([a[r],a[l-1]]=[a[l-1],a[r]],shuffle(a,l-1)):a;var arr=Array.from({length:3000},(_,i)=>i);console.time(“shuffle”);洗牌(arr);console.timeEnd(“shuffle”);

问题是,JS无法与大型递归合作。在这种特殊的情况下,数组大小会受到限制,大约为3000~7000,这取决于浏览器引擎和一些未知的事实。

我在考虑在控制台上粘贴oneliner。sort的所有技巧都给出了错误的结果,下面是我的实现:

 ['Bob', 'Amy', 'Joy'].map((person) => `${Math.random().toFixed(10)}${person}`).sort().map((person) => person.substr(12));

但不要在生产代码中使用它,它不是最佳的,只适用于字符串。

var shuffle = function(array) {
   temp = [];
   originalLength = array.length;
   for (var i = 0; i < originalLength; i++) {
     temp.push(array.splice(Math.floor(Math.random()*array.length),1));
   }
   return temp;
};