使用 reduce 从简单数组到二维数组(ft. logical AND &&)
From simple array to 2D array using reduce (ft. logical AND &&)
我需要将一个简单的平面数组“转换”为二维数组,然后我继续查看它对参数的说明。
我试图重新创建 this answer 的代码,但我得到了这个错误:
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
returns 数组的新长度 - 但累加器需要是 数组 ,而不是长度。
没有 &&
,并将代码缩进多行以使其更清楚发生了什么,第二个代码等同于:
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
而不是数字。
Shouldn't the code throw an error before to reach the &&?
确实如此。在second迭代时抛出错误,当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);
我需要将一个简单的平面数组“转换”为二维数组,然后我继续查看它对参数的说明。
我试图重新创建 this answer 的代码,但我得到了这个错误:
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
returns 数组的新长度 - 但累加器需要是 数组 ,而不是长度。
没有 &&
,并将代码缩进多行以使其更清楚发生了什么,第二个代码等同于:
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
而不是数字。
Shouldn't the code throw an error before to reach the &&?
确实如此。在second迭代时抛出错误,当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);