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

JavaScript递归过滤数组:移除最终categories为空的嵌套对象

处理多层嵌套分类的过滤方案

问题说明

给定如下示例数据:

let data = [
{
    id: 900,
    name: 'bar',
    slug: 'julep-mask',
    status: 'publish',
    categories: [{
        id: 43,
        name: 'Beauty',
        slug: 'beauty',
        categories: [{
            id: 777,
            name: 'Beauty',
            slug: 'asdfghjkl',
            categories: [{
                id: 999999,
                name: 'Antony',
                slug: 'Moss',
            }]
        }]
    }]
},
{
    id: 700,
    name: 'foo',
    slug: 'julep-mask',
    status: 'publish',
    categories: [{
        id: 43,
        name: 'Beauty',
        slug: 'beauty',
        categories: [{
            id: 777,
            name: 'Beauty',
            slug: 'asdfghjkl',
            categories: []
        }]
    }]
},
{
    id: 999,
    name: 'foobar',
    slug: 'julep-mask',
    status: 'publish',
    categories: [{
        id: 43,
        name: 'Beauty',
        slug: 'beauty',
        categories: [{
            id: 777,
            name: 'Beauty',
            slug: 'asdfghjkl',
            categories: [{
                id: 12345678,
                name: 'Jo',
                slug: 'Bloggs',
            }]
        }]
    }]
},
{
    id: 11111,
    name: 'fib',
    slug: 'julep-mask',
    status: 'publish',
    categories: [{
        id: 43,
        name: 'Beauty',
        slug: 'beauty',
        categories: [{
            id: 777,
            name: 'Beauty',
            slug: 'asdfghjkl',
            categories: []
        }]
    }]
}];

需求是移除所有最终categories数组为空的对象,期望结果为[{ id: 999 }, { id: 900 }]。现有代码仅能处理第二层嵌套,无法适配深层结构:

const populatedCategories = categories.map(category => {
    const categories = category.categories.filter(cat => cat.categories);
    if (categories.length) {
        return {
            ...category,
            categories
        };
    }
    return null;
}).filter(p => p);

解决方案

针对多层嵌套结构,必须用递归遍历整个分类树,判断每条分类链是否有效(即不会终止于空的categories数组)。

1. 编写递归判断函数

先实现一个辅助函数,检查单个分类节点是否存在有效的分类链:

function hasValidCategoryChain(category) {
    // 如果当前分类有categories数组
    if (category.categories) {
        // 数组为空则这条链无效
        if (category.categories.length === 0) {
            return false;
        }
        // 递归检查子分类,只要有一条链有效就返回true
        return category.categories.some(child => hasValidCategoryChain(child));
    }
    // 没有categories字段,说明是有效叶子节点
    return true;
}

2. 过滤并生成结果

用上述函数过滤原数据,保留存在有效分类链的对象,再提取id字段:

const filteredData = data.filter(item => {
    // 检查当前对象的所有分类中是否有有效链
    return item.categories.some(category => hasValidCategoryChain(category));
}).map(item => ({ id: item.id }));

console.log(filteredData);
// 输出:[{ id: 900 }, { id: 999 }](顺序可能因数组遍历顺序略有不同)

逻辑解释

  • 递归函数hasValidCategoryChain会逐层深入分类节点:
    • 若节点的categories数组为空,直接标记为无效;
    • 若数组非空,递归检查每个子节点,只要有一个子节点的链有效,当前节点就有效;
    • 若节点没有categories字段,说明是实际的叶子分类,标记为有效。
  • 过滤时,只要数据对象的任意一个分类存在有效链,就保留该对象,最终提取id得到目标结果。

内容的提问来源于stack exchange,提问作者Antony Moss

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 22:16:17