我如何改变阵列?

Ans*_*hul 447 javascript

可能重复:
如何随机化一个javascript数组?

我想在JavaScript中随机播放一系列元素,如下所示:

[0, 3, 3] -> [3, 0, 3]
[9, 3, 6, 0, 6] -> [0, 3, 6, 9, 6]
[3, 3, 6, 0, 6] -> [0, 3, 6, 3, 6]
Run Code Online (Sandbox Code Playgroud)

Jef*_*eff 904

使用现代版本的Fisher-Yates shuffle算法:

/**
 * Shuffles array in place.
 * @param {Array} a items An array containing the items.
 */
function shuffle(a) {
    var j, x, i;
    for (i = a.length - 1; i > 0; i--) {
        j = Math.floor(Math.random() * (i + 1));
        x = a[i];
        a[i] = a[j];
        a[j] = x;
    }
    return a;
}
Run Code Online (Sandbox Code Playgroud)

ES2015(ES6)版本

/**
 * Shuffles array in place. ES6 version
 * @param {Array} a items An array containing the items.
 */
function shuffle(a) {
    for (let i = a.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [a[i], a[j]] = [a[j], a[i]];
    }
    return a;
}
Run Code Online (Sandbox Code Playgroud)

但请注意,截至2017年10月,使用解构分配交换变量会导致重大的性能损失.

使用

var myArray = ['1','2','3','4','5','6','7','8','9'];
shuffle(myArray);
Run Code Online (Sandbox Code Playgroud)

  • 此方法(以及下面的方法)都修改原始数组.这没什么大不了的,但是如何调用它的例子有点奇怪. (15认同)
  • @RobG const 是一个完美的选择,因为它是块作用域的,与 var 不同,并且在每次交互后都会重新声明。let 也可以工作,但是由于 j 不会改变它的值,因此 for block const 是更好的选择 (3认同)
  • @Michael +1 指出重新分配是不必要的。事实上,它具有误导性,可能应该是此评论线程中指出的第一件事。 (2认同)
  • 我发现ES6交换速度较慢(一旦我开始工作.你必须在[ - 更多的理由总是使用它们之前]有一个分号.). (2认同)

Ble*_*der 461

您可以使用Fisher-Yates Shuffle(代码改编自本网站):

function shuffle(array) {
    let counter = array.length;

    // While there are elements in the array
    while (counter > 0) {
        // Pick a random index
        let index = Math.floor(Math.random() * counter);

        // Decrease counter by 1
        counter--;

        // And swap the last element with it
        let temp = array[counter];
        array[counter] = array[index];
        array[index] = temp;
    }

    return array;
}
Run Code Online (Sandbox Code Playgroud)

  • 关于这个算法的杰夫阿特伍德非常有趣的帖子.http://blog.codinghorror.com/the-danger-of-naivete/我想知道为什么它的实现方式是 (25认同)
  • 为Array添加了一个漂亮的原型.可能"不安全"buuuuuuut ......在这里它无论如何.http://jsbin.com/ozayim/1/edit (5认同)
  • @ Volter9:因为分布不均匀. (5认同)
  • 第一个答案似乎有一个错误。大约每 15 次运行一次,我会得到一个额外的“未定义”列。http://jsfiddle.net/tomasswood/z8zm7/ (3认同)
  • 为什么你不使用随机 + Array.prototype.sort?与这两个答案相比,它更容易且代码更少。 (2认同)