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

我有一个这样的数组:

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

我如何随机化/洗牌?


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

请参阅https://github.com/coolaj86/knuth-shuffle

你可以在这里看到很棒的视觉效果(和原文链接到这里)

function shuffle(array) {
  var currentIndex = array.length, temporaryValue, randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {

    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex -= 1;

    // And swap it with the current element.
    temporaryValue = array[currentIndex];
    array[currentIndex] = array[randomIndex];
    array[randomIndex] = temporaryValue;
  }

  return array;
}

// Used like so
var arr = [2, 11, 37, 42];
arr = shuffle(arr);
console.log(arr);

下面是Durstenfeld shuffle的一个JavaScript实现,这是一个计算机优化的Fisher-Yates版本:

/**
 * Randomize array element order 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;
    }
}

Fisher-Yates算法通过为每个原始数组元素选择一个随机元素,然后将其从下一个绘图中排除。 就像随机从一副牌中挑选。

这种排除是通过将拾取的元素与当前元素交换,然后从余数中选取下一个随机元素,以聪明的方式完成的(由Durstenfeld发明,供计算机使用)。 为了获得最佳效率,循环向后运行,以便简化随机选取(它始终可以从0开始),并跳过最后一个元素,因为没有其他选择了。

该算法的运行时间为O(n)。 请注意,洗牌是在原地完成的。 因此,如果您不想修改原始数组,请先用.slice(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]]; // eslint-disable-line no-param-reassign
    }
}

[社区编辑:这个答案是不正确的; 看评论。 它留在这里供将来参考,因为这个想法并不罕见。]

[1,2,3,4,5,6].sort(function() {
  return .5 - Math.random();
});
链接地址: http://www.djcxy.com/p/85149.html

上一篇: How to randomize (shuffle) a JavaScript array?

下一篇: Shuffling a list of objects