从简单数组到使用 reduce 的 2D 数组(ft. 逻辑 AND &&&)



我需要"转换";将一个简单的平面数组转换为2D数组,然后我继续SO,看看它对这个论点有什么看法
我试图重新创建这个答案的代码,但我得到了这个错误:

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()之后时,如何修复错误。代码不应该在到达&&之前抛出错误吗

这是必需的,因为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
);

因为CCD_ 7评估为阵列的新长度。

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

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

因此返回CCD_ 9而不是数字。

代码不应该在到达&?

确实如此。错误是在第二次迭代中抛出的,当twoDArray[twoDArray.length-1]twoDArray是一个数字时,计算结果为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);

最新更新