如何随机(洗牌)JavaScript数组?

如何随机(洗牌)JavaScript数组?,javascript,arrays,random,shuffle,Javascript,Arrays,Random,Shuffle,我有这样一个数组: var arr1 = ["a", "b", "c", "d"]; 如何随机/洗牌?事实上的无偏洗牌算法是Fisher-Yates(又名Knuth)洗牌 看 你可以看到一个(和原来的帖子) 函数洗牌(数组){ var currentIndex=array.length,随机索引; //虽然还有一些元素需要洗牌。。。 而(0!==currentIndex){ //选择剩余的元素。。。 randomIndex=Math.floor(Math.random()*currentIn

我有这样一个数组:

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

如何随机/洗牌?

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

你可以看到一个(和原来的帖子)

函数洗牌(数组){
var currentIndex=array.length,随机索引;
//虽然还有一些元素需要洗牌。。。
而(0!==currentIndex){
//选择剩余的元素。。。
randomIndex=Math.floor(Math.random()*currentIndex);
当前索引--;
//并将其与当前元素交换。
[array[currentIndex],array[randomIndex]=[
数组[randomIndex],数组[currentIndex];
}
返回数组;
}
//像这样使用
var-arr=[2,11,37,42];
洗牌(arr);
控制台日志(arr)可以(或应该)使用它作为数组的原型:

克里斯托弗:

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;
}

下面是Fisher-Yates的优化版本的JavaScript实现:

/* 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)
注意洗牌是就地完成的,因此如果您不想修改原始数组,请首先使用制作副本


编辑:更新至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]];
    }
}

使用下划线.js库。对于这种情况,方法
\uuu0.shuffle()
很好。 以下是该方法的一个示例:

var _ = require("underscore");

var arr = [1,2,3,4,5,6];
// Testing _.shuffle
var testShuffle = function () {
  var indexOne = 0;
    var stObj = {
      '0': 0,
      '1': 1,
      '2': 2,
      '3': 3,
      '4': 4,
      '5': 5
    };
    for (var i = 0; i < 1000; i++) {
      arr = _.shuffle(arr);
      indexOne = _.indexOf(arr, 1);
      stObj[indexOne] ++;
    }
    console.log(stObj);
};
testShuffle();
var=require(“下划线”);
var-arr=[1,2,3,4,5,6];
//测试-洗牌
var testShuffle=函数(){
var指数=0;
var stObj={
'0': 0,
'1': 1,
'2': 2,
'3': 3,
'4': 4,
'5': 5
};
对于(变量i=0;i<1000;i++){
arr=随机播放(arr);
indexOne=u0.indexOf(arr,1);
stObj[indexOne]++;
}
console.log(stObj);
};
testShuffle();

添加到@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 shuffle=函数(数组){
温度=[];
originalLength=数组长度;
对于(变量i=0;i
警告
不建议使用此算法,因为它效率低且有强偏见;见评论。它被留在这里供将来参考,因为这个想法并不罕见



本教程直截了当地解释了这些区别。

Fisher-Yates的另一个实现,使用严格模式:

function shuffleArray(a) {
    "use strict";
    var i, t, j;
    for (i = a.length - 1; i > 0; i -= 1) {
        t = a[i];
        j = Math.floor(Math.random() * (i + 1));
        a[i] = a[j];
        a[j] = t;
    }
    return a;
}
递归解决方案:

function shuffle(a,b){
    return a.length==0?b:function(c){
        return shuffle(a,(b||[]).concat(c));
    }(a.splice(Math.floor(Math.random()*a.length),1));
};
新的

更短&可能更快的Fisher-Yates洗牌算法

  • 它使用while---
  • 按位到楼层(数字最多为10位十进制数字(32位))
  • 移除了不必要的闭包和其他东西

  • 脚本大小(函数名为fy):90字节

    演示

    *可能在除chrome之外的所有浏览器上都更快

    如果你有任何问题,尽管问

    编辑

    是的,它更快

    性能:

    使用顶级投票函数

    编辑 计算过多(不需要--c+1),没有人注意到

    更短(4字节)和更快(测试!)

    在其他地方缓存
    var rnd=Math.random
    然后使用
    rnd()
    也会略微提高大型阵列的性能

    可读版本(使用原始版本。这比较慢,变量是无用的,比如闭包&“;”,代码本身也比较短…请阅读此内容,顺便说一句,您无法在类似上面的javascript缩微器中压缩以下代码。)

    首先,看看javascript中不同排序方法的视觉对比

    其次,如果您快速查看上面的链接,您会发现与其他方法相比,
    随机顺序
    排序的性能相对较好,同时实现起来非常简单和快速,如下所示:

    function shuffle(array) {
      var random = array.map(Math.random);
      array.sort(function(a, b) {
        return random[array.indexOf(a)] - random[array.indexOf(b)];
      });
    }
    

    Edit:正如@gregers所指出的,使用值而不是索引调用比较函数,这就是为什么需要使用
    indexOf
    。请注意,此更改使代码不太适合较大的数组,因为
    indexOf
    在O(n)时间内运行。

    随机化数组

     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; 
    
    var arr=[“苹果”,“猫”,“亚当”,“123”,“佐罗”,“佩妮];
    var n=阵列长度;var tempArr=[];
    对于(变量i=0;i
    我在这个问题的副本上的“作者删除”答案中发现了这个变体。与其他一些已经有很多赞成票的答案不同,这是:

  • 实际上是随机的
  • 不在适当的位置(因此是
    shuffled
    名称,而不是
    shuffle
  • 此处尚未出现多个变体
  • 用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);
      }
    }
    

    使用ES2015,您可以使用以下选项:

    Array.prototype.shuffle = function() {
      let m = this.length, i;
      while (m) {
        i = (Math.random() * m--) >>> 0;
        [this[m], this[i]] = [this[i], this[m]]
      }
      return this;
    }
    
    用法:

    [1, 2, 3, 4, 5, 6, 7].shuffle();
    
    矮子
    function shuffle(array) {
      var random = array.map(Math.random);
      array.sort(function(a, b) {
        return random[array.indexOf(a)] - random[array.indexOf(b)];
      });
    }
    
     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; 
    
    Array.prototype.shuffled = function() {
      return this.map(function(n){ return [Math.random(), n] })
                 .sort().map(function(n){ return n[1] });
    }
    
    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.prototype.shuffle = function() {
      let m = this.length, i;
      while (m) {
        i = (Math.random() * m--) >>> 0;
        [this[m], this[i]] = [this[i], this[m]]
      }
      return this;
    }
    
    [1, 2, 3, 4, 5, 6, 7].shuffle();
    
    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;
    }
    
    const someArray = [1, 2, 3, 4, 5];
    
    someArray.sort(() => Math.random() - 0.5);
    
     /**
     * Returns a new array whose contents are a shuffled copy of the original array.
     * @param {Array} The items to shuffle.
     * https://stackoverflow.com/a/2450976/1673761
     * https://stackoverflow.com/a/44071316/1673761
     */
    const shuffle = (array) => {
      let currentIndex = array.length;
      let temporaryValue;
      let randomIndex;
      const newArray = array.slice();
      // While there remains elements to shuffle...
      while (currentIndex) {
        randomIndex = Math.floor(Math.random() * currentIndex);
        currentIndex -= 1;
        // Swap it with the current element.
        temporaryValue = newArray[currentIndex];
        newArray[currentIndex] = newArray[randomIndex];
        newArray[randomIndex] = temporaryValue;
      }
      return newArray;
    };
    
    let unshuffled = ['hello', 'a', 't', 'q', 1, 2, 3, {cats: true}]
    
    let shuffled = unshuffled
      .map((a) => ({sort: Math.random(), value: a}))
      .sort((a, b) => a.sort - b.sort)
      .map((a) => a.value)
    
    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;
    }
    
    ['a','b','c','d'].map(x => [Math.random(), x]).sort(([a], [b]) => a - b).map(([_, x]) => x);
    
    var myArr = ["a", "b", "c", "d"];
    
    myArr.forEach((val, key) => {
      randomIndex = Math.ceil(Math.random()*(key + 1));
      myArr[key] = myArr[randomIndex];
      myArr[randomIndex] = val;
    });
    // see the values
    console.log('Shuffled Array: ', myArr)
    
    //one line solution
    shuffle = (array) => array.sort(() => Math.random() - 0.5);
    
    
    //Demo
    let arr = [1, 2, 3];
    shuffle(arr);
    alert(arr);
    
    function shuffle(array) {
      return array.sort(() => Math.random() - 0.5);
    }