【问题标题】:From simple array to 2D array using reduce (ft. logical AND &&)使用 reduce (ft.logical AND &&) 从简单数组到二维数组
【发布时间】:2021-07-06 09:04:07
【问题描述】:

我需要将一个简单的平面数组“转换”为二维数组,然后我继续查看它对参数的看法。
我尝试重新创建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() 之后,如何修复错误。代码在到达&&之前不应该抛出错误吗?

【问题讨论】:

    标签: javascript arrays push reduce logical-and


    【解决方案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 而不是数字。

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

    确实如此。在 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);

    【讨论】:

    • 感谢您的清晰解释和建议!我想我终于明白了reduce 的工作原理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 2019-04-08
    • 2019-06-14
    • 1970-01-01
    • 1970-01-01
    • 2012-03-07
    • 1970-01-01
    相关资源
    最近更新 更多