Javascript 从嵌套数组中提取子数组

Javascript 从嵌套数组中提取子数组,javascript,arrays,recursion,Javascript,Arrays,Recursion,我有嵌套数组数据,我想将所有嵌套数组提取为其父数组的同级。我非常接近,但是我在结果中得到了一个额外的空数组,我无法确定它来自何处或者如何消除它 注意:我很想了解为什么会发生这种情况,以及如何在我的函数中消除它,而不仅仅是结果列表中的.filter(arr=>arr.length) 这是我迄今为止的尝试: var arrs=[ [1, 2, [3, 4], 5], [6, [7, 8, 9, [10, 11]]], [12, 13], [[14, 15], [16, 17]], [[1], 4,

我有嵌套数组数据,我想将所有嵌套数组提取为其父数组的同级。我非常接近,但是我在结果中得到了一个额外的空数组,我无法确定它来自何处或者如何消除它

注意:我很想了解为什么会发生这种情况,以及如何在我的函数中消除它,而不仅仅是结果列表中的
.filter(arr=>arr.length)

这是我迄今为止的尝试:

var arrs=[
[1, 2, [3, 4], 5],
[6, [7, 8, 9, [10, 11]]],
[12, 13],
[[14, 15], [16, 17]],
[[1], 4, [1, 1], 4]
];
//期望输出
// [
//   [1, 2, 5],
//   [3, 4],
//   [6],
//   [7, 8, 9],
//   [10, 11],
//   [12, 13],
//   [14, 15],
//   [16, 17],
//   [4, 4]
//   [1]
//   [1, 1]
// ]
函数提取阵列(arr){
返回arr.reduce((res,curr)=>{
if(数组isArray(当前)){
res=res.concat(提取阵列(当前));
}
否则{
res[0]。推送(当前);
}
返回res;
}, [[]]);
}
日志(提取阵列(ARR));
//结果:
// [ 

//[],您可以尝试以下代码

var arrs=[
[1, 2, [3, 4], 5],
[6, [7, 8, 9, [10, 11]]],
[12, 13],
[
[14, 15],
[16, 17]
], //  {
if(数组isArray(当前)){
res=res.concat(提取阵列(当前));
}否则{
设指数=0;

对于(设j=0;j),您可以在从函数返回时检查它

编辑:更多性能功能(检查stackblitz链接)


[[14,15],[16,17]]
这样的元素将在递归后引入一个
[]
。这应该通过检查长度来处理

var arrs=[
[1, 2, [3, 4], 5],
[6, [7, 8, 9, [10, 11]]],
[12, 13],
[[14, 15], [16, 17]],
[[1], 4, [1, 1], 4]
];
函数提取阵列(arr、acc=[]){
如果(arr.length==0)返回acc;
设pure=arr.filter(elm=>!Array.isArray(elm));
如果(纯长度>0){
加速推力(纯);
}
acc.concat(arr.filter(elm=>Array.isArray(elm)).map(elm=>extractArray(elm,acc));
返回acc;
}

log(extractaries(arrs));
我只是想分享我解决这个问题的方法,我喜欢尝试解决它,在我的例子中,我还将一个数组传递给
extractaries
方法,以便更容易捕获和过滤
arrs
参数中的每个数组

let result = [];
extractArrays(arrs, result);
console.log(result);

function extractArrays(arr, result) {
  let newResult = arr.reduce((acc, curr) => {
    if (Array.isArray(curr)) {
      extractArrays(curr, result);
    } else {
      acc.push(curr);
    }

    return acc;
  }, []);

  newResult.length && result.push(newResult);
}

编辑:下面这行的答案是一个很好的展平数组的方法,但我建议这样做是因为我误解了这个问题。我会留下它,以防有人知道它,但为了保持准确的记录,我还将更新我的答案以解决问题中提出的问题

接受的答案似乎足够了,但我会尝试一下。我会使用
数组。reduce
一次性覆盖所有内容,并在内部使用
数组。filter
将正常项目与数组项目分开,然后在嵌套数组上使用spread
操作符,以便将所有内容推送到相同的l在所有嵌套数组上递归调用相同的提取函数后。老实说,解释可能比代码更难理解,看看:

const数据=[
[1, 2, [3, 4], 5],
[6, [7, 8, 9, [10, 11]]],
[12, 13],
[[14, 15], [16, 17]],
[[1], 4, [1, 1], 4]
]
const extractChildArrays=arrs=>arrs.reduce((acc,cur)=>{
const nestedArrs=cur.filter(a=>Array.isArray(a))
常量normalItems=cur.filter(a=>!Array.isArray(a))
acc.push(正常项,…提取子数组(嵌套子数组))
返回acc
}, [])

console.log(extractChildArrays(data))
您有:
[[]]
作为要减少的第二个参数,因此数组中的第一项是空数组。@fallereneaper是的,我也这么认为,但后来我的输出变成了
[1,2,3,4,5,6,…]
res[0]。推送(curr)
从不会在顶层发生。@ASDFGerte我明白你的意思。因此,基本上我必须在顶层单独处理子数组,然后将结果缝合在一起?这至少是可能的。只要你将空层作为空数组放入输出,你当前的输出就不会“错误”-顶层没有数字。根据我想要的输出,
[…,[1],[4,4],[1,1]
应该是
[…,[4,4],[1],[1,1]]
,但我认为在我的情况下,您的解决方案应该仍然有效。谢谢!这是对spread运算符的创造性使用,但是检查返回值中的长度并切掉第一个元素与只调用
extractArray(data).filter(arr=>arr.length)没有太大区别
+1'danyway@mhodges你是对的,几乎是一样的。添加了新的更快的函数。这不是我想要的输出。无论如何,谢谢。@mhodges啊,我的错,你仍然可以用这个来完成。flat的第一个参数是深度!@JonDeWitt,但你不知道深度beforehand@mhodges今天我在翻阅我的旧答案我想我会更新这个。这仍然不是我正在寻找的输出。我想保持数组的完整性,我只想让它们都处于顶层。请查看接受答案的输出。
function extractFaster(arr) {
  let res = [0];
  function recExtract(arr) {
    let hasNonArrayElm = false;
    let index = res.length -1;
    arr.forEach(curr => {
      if (!Array.isArray(curr)) {
        hasNonArrayElm ? res[index].push(curr) : res.splice(index, 0, [curr]);
        hasNonArrayElm = true;
        return;
      }
      recExtract(curr);
    });
  }

  recExtract(arr);
  res.splice(-1, 1)
  return res;
}
let result = [];
extractArrays(arrs, result);
console.log(result);

function extractArrays(arr, result) {
  let newResult = arr.reduce((acc, curr) => {
    if (Array.isArray(curr)) {
      extractArrays(curr, result);
    } else {
      acc.push(curr);
    }

    return acc;
  }, []);

  newResult.length && result.push(newResult);
}