使用JavaScript中的splice函数对数组进行切片的基本算法脚本化。

3

现在我正在做freecodecamp上的一道练习。目前我遇到了一个逻辑错误,但不知道失败原因。

在这段代码中,我需要编写一个函数,根据参数来切割输入的数组。测试结果应该如下:

chunkArrayInGroups(["a", "b", "c", "d"], 2) should return [["a", "b"], ["c", "d"]].
chunkArrayInGroups([0, 1, 2, 3, 4, 5], 3) should return [[0, 1, 2], [3, 4, 5]].
chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 4) should return [[0, 1, 2, 3], [4, 5, 6, 7], [8]].
chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 2) should return [[0, 1], [2, 3], [4, 5], [6, 7], [8]].

以下是我的代码:

function chunkArrayInGroups(arr, size) {
  var array = [];
  for (var x = 0; x < arr.length ; x+=size){
    var spliceArr = arr.splice(0,size);
    array.push(spliceArr);
  }
  array.push(arr);
  return array;
}

chunkArrayInGroups(["a", "b", "c", "d","e"], 2);

对于大多数情况,代码都能正常工作。但是对于最后一个条件,即

chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 2) should return [[0, 1], [2, 3], [4, 5], [6, 7], [8]].

在这种情况下,我无法得到正确的答案。我在控制台日志中进行了测试,结果输出如下:
[[0, 1], [2, 3], [4, 5], [6, 7, 8]].

我知道这不是一个难题,而且有很多更好的方法来解决它,但我能知道这段代码中的逻辑错误在哪里吗? 非常感谢!

6个回答

3

不要使用 splice,而是使用 slice。这也会确保原始数组不被修改。

像这样(演示):

function chunkArrayInGroups(arr, size) {
  var array = [];
  for (var x = 0; x < arr.length; x += size) {
     // take elements from current index (`x`) to `x` + `size`
     // (do not remove them from the original array, so the original size is not modified either)
    var sliceArr = arr.slice(x, x + size);
    array.push(sliceArr);
  }
  return array;
}


console.log(chunkArrayInGroups(["a", "b", "c", "d"], 2)); //should return [["a", "b"], ["c", "d"]].
console.log(chunkArrayInGroups([0, 1, 2, 3, 4, 5], 3)); // should return [[0, 1, 2], [3, 4, 5]].
console.log(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 4)); // should return [[0, 1, 2, 3], [4, 5, 6, 7], [8]].
console.log(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 2)); // should return [[0, 1], [2, 3], [4, 5], [6, 7], [8]]


2
可能对于你的循环,添加一个 console.log(arr) 可以帮助你查看数组随时间如何变化。
你会看到它看起来像这样:
[0, 1, 2, 3, 4, 5, 6, 7, 8]
[2, 3, 4, 5, 6, 7, 8]
[4, 5, 6, 7, 8]

然后,考虑您的最终拼接并添加在循环之外发生的内容:

[6, 7, 8]

由于您的循环按size递增,因此一旦它收集了所有恰好为size的子数组,它就会退出。

相反,我建议您继续直到输入为空:

function chunkArrayInGroups(arr, size) {
  var array = [];
  while(arr.length > 0){
    var spliceArr = arr.splice(0,size);
    array.push(spliceArr);
  }
  return array;
}


2

为了减少循环数组的次数,您需要停止使用大小。我们还保存了数组的长度,这样就不必每次都获取它,从而节省了操作。此外,您会注意到我没有使用var,因为您不应该使用它。请使用let来声明普通变量,使用const来声明不会被重新赋值的变量。

function chunkArrayInGroups(arr, size) {
  let array = [];
  let arrayLength = arr.length;
  for (let i = 0; i < arrayLength; i+=size) {
    array.push(arr.slice(i, i+size));
  }
  return array
}

console.log(chunkArrayInGroups(["a", "b", "c", "d"], 2), [["a", "b"], ["c", "d"]])
console.log(chunkArrayInGroups([0, 1, 2, 3, 4, 5], 3), [[0, 1, 2], [3, 4, 5]])
console.log(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 4), [[0, 1, 2, 3], [4, 5, 6, 7], [8]])
console.log(chunkArrayInGroups([0, 1, 2, 3, 4, 5, 6, 7, 8], 2), [[0, 1], [2, 3], [4, 5], [6, 7], [8]])

1
问题在于你正在迭代过程中缩小数组长度。也就是说,在每次迭代中,你的数组会变得更小,而 x 始终在增加。这意味着在最后一次迭代之前,x 将达到 6,而数组长度将为 3,因此 x < arr.length 的结果为 false,你的最后一次迭代不会发生。我能想到的最简单的解决方案是将原始数组长度存储在一个名为 stop 的变量中,并在循环外删除不必要的最终数组 push。

function chunkArrayInGroups(arr, size) {
  var array = [];
  var stop = arr.length;
  for (var x = 0; x < stop; x+=size){
    var spliceArr = arr.splice(0,size);
    array.push(spliceArr);
  }
  return array;
}

console.log(chunkArrayInGroups([1,2,3,4,5,6,7], 2))


1

splice 方法在每次迭代中都会更改数组的长度。这就是为什么您的循环在您期望之前退出的原因。您可以在此处阅读有关splice的更多信息。

splice 不同,slice 不会从数组中删除项目,因此lealceldeiro的答案将按预期工作。

Kevin Bruccoleri的答案看起来更干净、更简短,但如果您拥有一个应用程序,在其中将数组存储到变量中,然后将其传递给函数,那么在执行函数后,该变量将为空,这可能会导致应用程序中的错误。这就是为什么数组基本上是对象,但这是javascript的科学幻想。

function chunkArrayInGroups(arr, size) {
  var array = [];
  while (arr.length) {
    array.push(arr.splice(0, size))
  }
  return array
}

var nums = [0, 1, 2, 3, 4, 5, 6, 7, 8]
console.log('now it full', nums);
console.log(chunkArrayInGroups(nums, 2));
console.log('now it empty', nums);


-1

使用slice复制原始数组,使用map()splice()从n索引处插入数组

const frankenSplice = (arr1, arr2, n) => {
    let arr = arr2.slice();

    arr1.map(e => {
        arr.splice(n, 0, e);
        n++;
    })

    return arr;
}

1
请在您的答案中添加一些解释,以便其他人可以从中学习。 - Nico Haase

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接