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
相关产品推荐
相关产品推荐

