0

我需要将一个简单的平面数组“转换”为二维数组,然后我继续查看它对这个论点的看法。
我试图重新创建这个答案的代码,我得到了这个错误:

console.log(array.reduce((twoDArray, n, i) => (i % 3 == 0 ? twoDArray.push([n]) : twoDArray[twoDArray.length-1].push(n)), []));
                                                                                                                ^
TypeError: Cannot read property 'push' of undefined

问题是我没有&& twoDArray在箭头函数的末尾添加。在这里你可以看到:

let array = [1,2,3,4,5,6,7,8,9];

// this works
console.log(array.reduce((twoDArray, n, i) => (i % 3 == 0 ? twoDArray.push([n]) : twoDArray[twoDArray.length-1].push(n)) && twoDArray, []));

// here the second push() throws an error
console.log(array.reduce((twoDArray, n, i) => (i % 3 == 0 ? twoDArray.push([n]) : twoDArray[twoDArray.length-1].push(n)), []));

现在我不明白几件事,即:

  • 这是如何&& twoDArray工作的?它的目的是什么?
  • 当仅在push()生成错误之后放置此添加时,如何修复错误。代码不应该在到达之前抛出错误&&吗?
4

1 回答 1

1

这是必需的,因为push返回数组的新长度 - 但累加器需要是数组,而不是长度。

没有&&, 并将代码缩进多行以使发生的事情更清楚,第二个代码等效于:

let array = [1, 2, 3, 4, 5, 6, 7, 8, 9];

// here the second push() throws an error
console.log(array.reduce((twoDArray, n, i) => {
  return (i % 3 == 0 ? twoDArray.push([n]) : twoDArray[twoDArray.length - 1].push(n))
}, []));

如同:

let array = [1, 2, 3, 4, 5, 6, 7, 8, 9];

// here the second push() throws an error
console.log(array.reduce((twoDArray, n, i) => {
  return (
    i % 3 == 0
      ? twoDArray.push([n])
      : twoDArray[twoDArray.length - 1].push(n)
  );
}, []));

现在,问题应该很清楚了:无论输入哪个条件,回调都会计算为

  return (
    i % 3 == 0
      ? someNumber
      : someNumber
  );

因为.push计算为数组的新长度。

添加&& twoDArray到它使回调看起来像:

  return (
    i % 3 == 0
      ? someNumber
      : someNumber
  ) && twoDArray;

因此返回twoDArray而不是数字。

代码在到达&&之前不应该抛出错误吗?

确实如此。在第二次迭代时抛出错误,当twoDArray[twoDArray.length-1], whentwoDArray是一个数字时,计算结果为undefined,所以它不能被推送到。但是,twoDArray数字而不是数组的问题是由先前(第一次)迭代末尾的代码导致的:缺少&& twoDArray;.

像这样的代码非常令人困惑。如果代码变得不可读,请尽量不要将代码压缩成一行。另一个问题是,.reduce当累加器在每次迭代中都是同一个对象时,这可能是不合适的。考虑改为这样做:

let array = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const twoDArray= [];
array.forEach((n, i) => {
  i % 3 == 0
    ? twoDArray.push([n])
    : twoDArray[twoDArray.length - 1].push(n);
});
console.log(twoDArray);

并使用if/else代替条件运算符:

let array = [1, 2, 3, 4, 5, 6, 7, 8, 9];

const twoDArray= [];
array.forEach((n, i) => {
  if (i % 3 === 0) twoDArray.push([n])
  else twoDArray[twoDArray.length - 1].push(n);
});
console.log(twoDArray);

于 2021-04-10T20:37:47.593 回答