仅对数组的 returns 部分进行混洗

Shuffling an array only returns part of the array

我写了一个函数来打乱数组的元素。

function shuffle(arr) {
  var newarr = [];
  var oldarr = arr;
  for(var i = 0; i < arr.length; i++) {
    var index = Math.floor(Math.random() * arr.length);
    newarr.push(arr[index]);
    arr.splice(index, 1);
  }
  return newarr;
}

由于某种原因,该函数只returns一半的数组元素。如果将一个包含 7 个元素的数组传递给它,则它 returns 4 个元素。同样,如果返回一个有8个元素的数组。

我哪里错了?

只需将数组的长度存储在一个变量中,然后在 for-loop header 而不是 arr.length 中使用它。 var oldarr = arr 行在您的代码中没有任何作用。

const arr = [1, 2, 3, 4];

function shuffle(arr) {
  var newarr = [];
  const length = arr.length;

  for (var i = 0; i < length; i++) {
    var index = Math.floor(Math.random() * arr.length);
    newarr.push(arr[index]);
    arr.splice(index, 1);
  }

  return newarr;
}

console.log(shuffle(arr));

请注意,这只是您问题的快速解决方案,并非推荐的解决方案。

然后回答你的问题 - 为什么当你有 4 个项目的数组时,将返回只有 2 个项目的数组 - 让我们看看你在每次迭代中减少数组长度的循环的执行.

iteration;   i;   arr.length;   i < arr.length
   1         0        4             true
   2         1        3             true
   3         2        2             false

有很多 Q&A on Whosebug 提供了正确有效的算法。在您的代码中,循环变量递增到 arr.length,但在每次迭代中,您将 length 减少为 splice,因此总的来说,i 只会 运行 大约是原始长度的一半,因此你的函数 returns 是一个大约输入大小一半的数组。

快速修复:使用 while 循环代替 for 循环:

while (arr.length) {

可选:为了完整保留输入数组,请替换以下无用的赋值:

var oldarr = arr;

...带有复制语句:

arr = arr.slice();