我需要"转换";将一个简单的平面数组转换为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);