如何将对象数组过滤并整理为按大洲(Continent)、国家(Country)、城市(City)层级组织的单个对象
嘿,我懂你现在的需求啦——要把那组带location层级的数据转换成 Continent→Country→City 嵌套结构的对象,还要兼容部分大洲/国家没有对应城市的情况对吧?你一开始用reduce的思路完全没问题,只是需要完善层级嵌套的逻辑,咱们一步步来搞定它!
完整解决方案代码
const data = [ { location: [{ name: 'Africa', type: 'Continent' }, { name: 'Angola', type: 'Country' }, { name: 'Luanda', type: 'City' } ], values: [] }, { location: [{ name: 'Europe', type: 'Continent' }, { name: 'Italy', type: 'Country' }, { name: 'Rome', type: 'City' } ], values: [] }, { location: [{ name: 'Europe', type: 'Continent' }, { name: 'Spain', type: 'Country' }, { name: 'Valencia', type: 'City' } ], values: [] }, { location: [{ name: 'Asia', type: 'Continent' }, { name: 'Japan', type: 'Country' } ], values: [1,2,3] } // 测试无城市的边界场景 ]; const result = data.reduce((acc, item) => { // 从当前项的location中提取各层级名称,用可选链处理缺失情况 const continent = item.location.find(loc => loc.type === 'Continent')?.name || null; const country = item.location.find(loc => loc.type === 'Country')?.name || null; const city = item.location.find(loc => loc.type === 'City')?.name || null; // 无大洲信息的项直接跳过,避免无效数据 if (!continent) return acc; // 初始化大洲层级:如果不存在则创建带countries属性的对象 if (!acc[continent]) { acc[continent] = { countries: {} }; } // 处理无国家的场景:将values直接挂载到大洲层级 if (!country) { acc[continent].values = item.values; return acc; } // 初始化国家层级:如果不存在则创建带cities属性的对象 if (!acc[continent].countries[country]) { acc[continent].countries[country] = { cities: {} }; } // 处理无城市的场景:将values挂载到国家层级 if (!city) { acc[continent].countries[country].values = item.values; return acc; } // 最后初始化城市层级,并挂载values acc[continent].countries[country].cities[city] = { values: item.values }; return acc; }, {}); console.log(result);
关键逻辑拆解
- 层级提取:用
find配合可选链?.安全获取大洲、国家、城市名称,避免找不到对应type时报错。 - 层级初始化:遍历过程中检查每个层级是否存在,不存在则创建对应的结构,确保同一大洲下的多个国家不会被覆盖。
- 边界兼容:专门处理了无国家、无城市的场景,让values能挂载到对应的最高层级上。
- 累加器更新:每一步都返回更新后的累加器
acc,确保reduce能持续构建嵌套结构。
运行结果验证
执行代码后会得到你想要的结构,同时兼容了无城市的测试项:
{ Africa: { countries: { Angola: { cities: { Luanda: { values: [] } } } } }, Europe: { countries: { Italy: { cities: { Rome: { values: [] } } }, Spain: { cities: { Valencia: { values: [] } } } } }, Asia: { countries: { Japan: { values: [1,2,3], cities: {} } } } }
为什么你之前的代码没达到预期?
你之前只完成了大洲层级的初始化,没有深入处理国家和城市的嵌套逻辑,也没做同一大洲下多国家的合并判断——现在的代码会自动检查现有层级,在已有大洲/国家的基础上继续添加子层级,不会覆盖已有数据。
内容的提问来源于stack exchange,提问作者SixtyEight
相关产品推荐
相关产品推荐

