js中的随机数组

shuffle array in js

我想在 javascript...

中打乱数组

我第一次写这个函数:

function shuffle(arr) {
    for (i = 0; i < arr.length; i++) {
        let temp0 = arr[Math.floor(Math.random() * arr.length)];
        let temp1 = arr[Math.floor(Math.random() * arr.length)];
        console.log(temp0); // select random item work correctly
        console.log(temp1); // select random item work correctly
        if (temp0 === temp1) { //for dont change arr[index] with save value!!!
            continue;
        }
        temp2 = temp0;
        temp0 = temp1;
        temp1 = temp2;
        console.log(temp0); //all temp0, temp1, temp2 are equal!!!
        console.log(temp1); //all temp0, temp1, temp2 are equal!!!
        console.log(temp2); //all temp0, temp1, temp2 are equal!!!
    }
    return arr
}

我的算法如下:

但我最终得到 temp0、temp1 和 temp2 都相等!!!

然后我将我的代码更改为这个并且它完美运行

function shuffle1(arr) {
    for (i = 0; i < arr.length; i++) {
        x = Math.floor(Math.random() * arr.length);
        y = Math.floor(Math.random() * arr.length);
        if (x === y) { //for dont change arr[index] with self !!!
            continue;
        }
        temp0 = arr[x];
        arr[x] = arr[y];
        arr[y] = temp0;
    }
    return arr
}

唯一发生的变化是:随机创建的索引编号分配给一个变量,然后该变量用于select数组中的一个项目。

谁能帮我理解为什么第一个例子在第二个例子中没有按预期工作?

提前致谢

使用 Fisher 方法应该更有效:

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

原答案:

它不更新的原因是你正在更新的数字没有引用数组中的元素。让我们看看节点 REPL。

我们将创建一个数组并尝试以两种方式更新它,看看是否在数组中看到了更新。

> let a = [1,2,3]
undefined
> let f = a[0]  // grab reference to 1st element
undefined
> f
1
> f = 2         // 1. try to update via our variable
2
> a[0]          
1               // update has NOT worked
> a[0] = 2      // 2. try to update by array index
2
> a[0]          
2               // update has worked

一旦我们将第一个函数更改为通过数组索引更新,两个函数就相同了。

当我更新 f 时,我为它分配了一个新的数字对象,并用 a[0] 打破了 link,它仍然指的是旧数字。在 js 中,数字是不可变的,所以我们不能更新它们,即使我们想更新。

相关: Is number in JavaScript immutable?