You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移除嵌套数组/对象中的空数组?

问题描述

我有一个嵌套的对象数组,每个对象包含children数组,部分children为空数组。需要遍历整个结构,删除所有空的children数组以及对应的父对象(如果它的children处理后为空)。

示例数据:

let a = [
  {children: [{children: [1,2]}, {children: [5,6]}]},
  {children: [{children: []}, {children: [5,6]}]},
  {children: [{children: []}, {children: []}]},
  {children: []}
]

尝试了以下代码,却报错:cannot read property 'children' of undefined

function removeEmpty(array){
  for(var i=array.length-1;i>=0;i--){
      if(array[i].children){
          if(array[i].children.length){
              for(var j=array[i].children.length-1;j=>0;j--){
                  if(array[i].children[j].children){
                      removeEmpty(array[i].children[j])
                  }else{
                      array[i].splice[j,1]
                  }
              }
              
              if(!array[i].children.length){
                  array.splice(i,1)
              }
          }else{
              array.splice(i,1)
          }
      }
  }
}

removeEmpty(a)

预期结果:

let expectedOutcome = [
  {children: [{children: [1,2]}, {children: [5,6]}]},
  {children: [{children: [5,6]}]}
]

错误原因分析

原代码存在几个明显问题:

  1. 循环条件错误:j=>0 是语法错误,应该写成 j>=0,这会导致循环逻辑混乱,甚至访问不存在的数组索引。
  2. 方法调用错误:array[i].splice[j,1] 把数组方法splice当成了数组,正确写法是array[i].children.splice(j, 1)。
  3. 递归参数错误:removeEmpty(array[i].children[j]) 传入的是单个对象,但removeEmpty的参数要求是数组,应该传入array[i].children[j].children。
  4. 逻辑不完整:递归处理子数组后,没有重新检查当前对象的children是否为空,导致无法正确删除子节点全被清理后的父对象。

修复后的解决方案

方案1:原地修改原数组

这个方案直接修改输入的数组,适合不需要保留原数据的场景:

function removeEmpty(array) {
  // 从后往前遍历,避免删除元素导致索引错乱
  for (let i = array.length - 1; i >= 0; i--) {
    const currentItem = array[i];
    // 确保当前元素存在children且是数组
    if (currentItem.children && Array.isArray(currentItem.children)) {
      // 递归清理子children数组
      removeEmpty(currentItem.children);
      // 子数组清理后为空,则删除当前元素
      if (currentItem.children.length === 0) {
        array.splice(i, 1);
      }
    } else {
      // 没有children或不是数组的元素直接删除
      array.splice(i, 1);
    }
  }
}

// 测试
let a = [
  {children: [{children: [1,2]}, {children: [5,6]}]},
  {children: [{children: []}, {children: [5,6]}]},
  {children: [{children: []}, {children: []}]},
  {children: []}
];

removeEmpty(a);
console.log(a);
// 输出符合预期结果

方案2:纯函数(返回新数组,不修改原数据)

如果需要保留原数组,推荐使用纯函数,返回处理后的新数组:

function removeEmptyPure(array) {
  return array.reduce((result, currentItem) => {
    // 过滤掉没有children或children不是数组的元素
    if (!currentItem.children || !Array.isArray(currentItem.children)) {
      return result;
    }
    // 递归清理子数组
    const cleanedChildren = removeEmptyPure(currentItem.children);
    // 只有子数组清理后不为空,才保留当前对象
    if (cleanedChildren.length > 0) {
      result.push({ ...currentItem, children: cleanedChildren });
    }
    return result;
  }, []);
}

// 测试
let a = [
  {children: [{children: [1,2]}, {children: [5,6]}]},
  {children: [{children: []}, {children: [5,6]}]},
  {children: [{children: []}, {children: []}]},
  {children: []}
];

const result = removeEmptyPure(a);
console.log(result);
// 输出预期结果

内容的提问来源于stack exchange,提问作者Hassan Raza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 06:54:07