在javascript中使用reduce和recursion来展平嵌套数组

如何解决在javascript中使用reduce和recursion来展平嵌套数组

我发现了这个有趣的代码示例,它使用 recursionreduce 函数而不是 flat 来展平数组。除了以下内容,我明白了它的作用:

  1. acc = acc.concat(flatWithRec(item)); 为什么要重新分配累加器?在减少功能中怎么可能? 为什么在这里使用 concat

  2. return acc; 为什么会返回 acc?每次调用函数都是一个新的平面数组吗?

  3. 有没有办法仍然使用递归并使读者更容易理解?

请说明

function flatWithRec(arr) {
  const flatArray = arr.reduce((acc,item) => {
    if (Array.isArray(item)) {
      acc = acc.concat(flatWithRec(item));
    } else {
      acc.push(item);
    }
    return acc;
  },[]);
  return flatArray;
}


console.log(flatWithRec([1,[2,3,[4],[5,6,[7]]
]]))
// output: [1,2,4,5,7])

解决方法

  1. 累加器是一个数组。您重新分配给它一个新数组,该数组包含您在循环开始时的项目和要添加的数组项目的项目。如评论中所述,acc.concat 返回一个新数组,其中包含传入参数的数组项。见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat

  2. 您需要在每次循环结束时返回累加器,以便在下一次循环中考虑新值。

  3. Javascript recursive array flattening

,
  1. acc = acc.concat(flatWithRec(item)); 为什么要重新分配累加器?在减少功能中怎么可能?为什么在这里使用 concat

累加器 (acc) 是一个函数参数,可以重新分配,尽管这样做不是一个好习惯。 Concat 合并两个项(数组或其他),并返回一个新数组,因此您需要将其分配给 acc 作为当前循环的结果。

  1. return acc; 为什么会返回 acc?每次调用函数时都是一个新的平面数组吗?

累加器保存减少项的当前状态,在您的情况下是每次循环后的当前平面数组。您需要返回它,以便下一个循环可以继续累积。

  1. 有没有办法仍然使用递归并使读者更容易理解?

我对 flatWithRec 的看法 - 总是串联,但如果它是一个数组,则在串联之前调用 flatWithRec

function flatWithRec(arr) {
  return arr.reduce((acc,item) =>
    acc.concat(
      Array.isArray(item) 
        ? flatWithRec(item)
        : item
    ),[]);
}

const result = flatWithRec([1,[2,3,[4],[5,6,[7]]]])

console.log(result) // output: [1,2,4,5,7])

,

因此,reduce 方法的回调会针对数组中的每一项运行,并且从 iteration x 返回的任何内容都将作为第一个参数传递给 iteration x+1 。因此,必须确保在每次迭代期间返回正确的状态。

acc = acc.concat(flatWithRec(item)) 为什么要重新分配累加器?在 reduce 函数中怎么可能?为什么在这里使用 concat

因此,我们将 acc 的返回值分配给 concat,因为 concat 不会更改原始数组,而是返回一个新数组。累加器就像任何其他参数一样,因此您可以重新分配。完全没有必要使用 concat (使用 pushspread 在最后查看我的解决方案)

return acc; 为什么会返回 acc?每次调用函数都是一个新的平面数组吗?

如前所述,您需要从回调中返回正确的状态。是的,在每次迭代期间,都会创建一个新数组(性能不佳,请参阅最后的解决方案)

有没有办法仍然使用递归并让读者更容易理解?

我不知道对读者来说更容易,但这是我使用 => functionsspread 的解决方案。

const flatWithRec = (arr) =>
  arr.reduce((acc,item) => (
    Array.isArray(item) ? acc.push(...flatWithRec(item)) : acc.push(item),acc
  ),[]);

console.log(flatWithRec([1,[7]]]]));

,

是的,有一种方法可以使用递归并使其更易于理解:

function f(A,i=0){
  return i == A.length ? [] : (Array.isArray(A[i]) ? f(A[i]) : [A[i]]).concat(f(A,i+1));
}

var A = [1,[7]]]];

console.log(JSON.stringify(A));
console.log(JSON.stringify(f(A)));

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?