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

如何在JavaScript中递归查询嵌套分类对象的顶级父类名称?

问题描述

现有嵌套结构的分类对象states,产品数组中存储了任意层级的分类ID,需要根据分类ID获取其顶级父类名称(例如ID为24时,要拿到"Category #1")。当前使用的filter函数只能查询一级分类,无法处理深层分类。


现有分类对象结构

{
    "1": {
        "id": "1",
        "name": "Category #1",
        "hasChild": "Y",
        "count": "0",
        "parentId": null,
        "link": "/catalog/",
        "subcategories": [
            {
                "id": "21",
                "name": "Subcategory #1",
                "hasChild": "Y",
                "count": "0",
                "parentId": "1",
                "link": "/catalog/",
                "subcategories": [
                    {
                        "id": "24",
                        "name": "subsubcategory #1",
                        "hasChild": "Y",
                        "count": "1",
                        "parentId": "21",
                        "link": "/catalog/",
                        "subcategories": [],
                    },
                    {
                        "id": "25",
                        "name": "subsubcategory #2",
                        "hasChild": "Y",
                        "count": "0",
                        "parentId": "21",
                        "link": "/catalog/",
                        "subcategories": [],
                    }
                ],
            },
            {
                "id": "22",
                "name": "Subcategory #2",
                "hasChild": "Y",
                "count": "0",
                "parentId": "1",
                "link": "/catalog/",
            },
            {
                "id": "23",
                "name": "Subcategory #3",
                "hasChild": "Y",
                "count": "0",
                "parentId": "1",
                "link": "/catalog/",
            }
        ],
    },
    "2": {
        "id": "2",
        "name": "Category #2",
        "hasChild": "Y",
        "count": "0",
        "parentId": null,
        "link": "/catalog/",
        "subcategories": [
            // 子分类省略
        ],
    },
}

产品关联分类ID示例

["24", "22", "2"]

现有函数问题

现有filter函数无法查询深层分类,核心问题是代码中判断子分类的字段为i.children,但实际分类结构中子分类字段是subcategories,导致递归无法进入深层节点:

function filter(item, search, textKey) {
    let result = []
    const _filter = (item, search, textKey) => {
        for (const i of item) {
            if (i[textKey].indexOf(search) !== -1) {
                result = [...result, { name: i.name, id: i.id, parentId: i.parentId }]
            }
            // 错误:实际子分类字段是subcategories,不是children
            i.children ? _filter(i.children, search, textKey) : null
        }
    }
    _filter(item, search, textKey)
    return result
}

测试结果:

console.log(filter(Object.values(states), '24', 'id')) // 无结果
console.log(filter(Object.values(states), '2', 'id')) // 正常返回一级分类

解决方案

第一步:修复递归查询,找到目标分类节点

将子分类字段修正为subcategories,同时优化逻辑,找到目标后可提前终止递归:

// 递归查找任意层级的分类节点
function findCategoryNode(categories, targetId) {
    for (const category of categories) {
        if (category.id === targetId) {
            return category;
        }
        // 递归遍历子分类
        if (category.subcategories && category.subcategories.length > 0) {
            const found = findCategoryNode(category.subcategories, targetId);
            if (found) return found;
        }
    }
    return null;
}

第二步:根据节点追溯顶级父类

拿到目标节点后,通过parentId向上遍历,直到找到parentId为null的顶级分类:

// 根据分类ID获取顶级父类名称
function getTopParentCategoryName(states, targetId) {
    // 先找到目标分类节点
    const targetNode = findCategoryNode(Object.values(states), targetId);
    if (!targetNode) return null;

    // 向上追溯顶级父类
    let currentNode = targetNode;
    while (currentNode.parentId !== null) {
        currentNode = states[currentNode.parentId];
    }
    return currentNode.name;
}

使用示例

// 测试ID为24的情况
console.log(getTopParentCategoryName(states, '24')); // 输出 "Category #1"
// 测试ID为22的情况
console.log(getTopParentCategoryName(states, '22')); // 输出 "Category #1"
// 测试ID为2的情况
console.log(getTopParentCategoryName(states, '2')); // 输出 "Category #2"

可选优化:扁平化分类提升查询效率

如果需要频繁查询,可提前将所有分类节点扁平化存储,减少递归开销:

// 扁平化所有分类节点到对象中
function flattenCategories(states) {
    const flatMap = {};
    function traverse(categories) {
        for (const cat of categories) {
            flatMap[cat.id] = cat;
            if (cat.subcategories && cat.subcategories.length > 0) {
                traverse(cat.subcategories);
            }
        }
    }
    traverse(Object.values(states));
    return flatMap;
}

// 提前生成扁平化映射
const flatCategories = flattenCategories(states);

// 优化后的顶级父类查询
function getTopParentNameOptimized(flatCategories, states, targetId) {
    let currentNode = flatCategories[targetId];
    if (!currentNode) return null;
    while (currentNode.parentId !== null) {
        currentNode = states[currentNode.parentId];
    }
    return currentNode.name;
}

// 使用优化后的函数
console.log(getTopParentNameOptimized(flatCategories, states, '24')); // 输出 "Category #1"

内容的提问来源于stack exchange,提问作者Timur Iskakov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:10:32