JavaScript实现JSON按区-市镇-教区三级嵌套分组
需求说明
- 目标是构建三级嵌套的葡萄牙行政区划JSON文件,层级关系为:区(district) → 市镇(municipality) → 教区(parish)
- 期望输出结构示例:
{ "district": "Aveiro", "OfficialCodeDistrict": "01", "municipalities": [ { "municipality": "Arouca", "OfficialCodeMunicipality": "0104", "parishes": [ { "parish": "Fermedo", "OfficialCodeParish": {} }, { "parish": "Várzea", "OfficialCodeParish": "010420" }, { "parish": "Escariz", "OfficialCodeParish": "010409" }, { "parish": "Mansores", "OfficialCodeParish": "010413" } ] }, { "municipality": "Águeda", "OfficialCodeMunicipality": "0101", "parishes": [ { "parish": "Fermentelos", "OfficialCodeParish": "010109" }, { "parish": "Préstimo e Macieira de Alcoba", "OfficialCodeParish": "010127" } ] } ] }
- 已完成第一步:将原始数据按区做一级分组,实现代码如下:
const result = Object.entries(locations.reduce((acc, { OfficialCodeDistrict, OfficialNameDistrict, OfficialCodeMunicipality, OfficialNameMunicipality, OfficialNameParish, Type }) => { acc[OfficialNameDistrict] = (acc[OfficialNameDistrict] || []); acc[OfficialNameDistrict].push({ OfficialCodeDistrict, OfficialCodeMunicipality, OfficialNameMunicipality, OfficialNameParish, Type }); return acc; }, {})).map(([key, value]) => ({ district: key, municipalities: value })); console.log(result);
- 当前进展:已写出遍历每个区、对区内数据按市镇做二级分组的循环逻辑,可以独立生成每个区下按市镇归类的结果,但不知道如何将二级分组结果合并回一级分组的区对象中,现有循环代码如下:
let counter = 0; // 遍历所有区,对区内市镇做分组 while (counter < result.length){ result2 = Object.entries(result[counter]['municipalities'].reduce((acc, { OfficialCodeMunicipality, OfficialNameMunicipality, OfficialNameParish, Type }) => { acc[OfficialNameMunicipality] = (acc[OfficialNameMunicipality] || []); acc[OfficialNameMunicipality].push({ OfficialCodeMunicipality, OfficialNameParish, Type }); return acc; }, {})).map(([key, value]) => ({ municipality: key, parishes: value })); console.log(result2); // 目前已经可以为每个区生成独立的按市镇分组的JSON对象,例如Portalegre区可生成包含15个市镇条目的对象,所有区都能正常生成对应分组结果,但还未达到最终效果 counter++; }
实现方法
不需要单独声明result2存储临时分组结果,遍历区对象时直接把二级分组得到的市镇列表赋值给当前区对象的municipalities属性即可,同时补全各级缺失的官方编码字段、修正教区层级的字段映射,完整实现代码如下:
// 一级分组:按区归类 const result = Object.entries( locations.reduce((acc, curr) => { const { OfficialCodeDistrict, OfficialNameDistrict } = curr; acc[OfficialNameDistrict] = acc[OfficialNameDistrict] || []; acc[OfficialNameDistrict].push(curr); return acc; }, {}) ).map(([districtName, districtEntries]) => { // 提取当前区的官方编码(同一区编码一致,取第一条即可) const OfficialCodeDistrict = districtEntries[0].OfficialCodeDistrict; // 二级分组:按市镇归类 const municipalities = Object.entries( districtEntries.reduce((acc, curr) => { const { OfficialCodeMunicipality, OfficialNameMunicipality } = curr; acc[OfficialNameMunicipality] = acc[OfficialNameMunicipality] || []; acc[OfficialNameMunicipality].push(curr); return acc; }, {}) ).map(([municipalityName, municipalityEntries]) => { // 提取当前市镇的官方编码(同一市镇编码一致,取第一条即可) const OfficialCodeMunicipality = municipalityEntries[0].OfficialCodeMunicipality; // 组装当前市镇下的所有教区列表 const parishes = municipalityEntries.map(entry => ({ parish: entry.OfficialNameParish, OfficialCodeParish: entry.OfficialCodeParish || {} })); return { municipality: municipalityName, OfficialCodeMunicipality, parishes }; }); return { district: districtName, OfficialCodeDistrict, municipalities }; }); console.log(result);
代码说明:
- 同一区、同一市镇的官方编码是固定值,不需要在分组时重复存储,直接取分组下第一条数据的对应编码字段即可
- 教区层级直接映射原始数据的教区名称和教区编码,缺失编码的场景默认赋值为空对象,和示例结构保持一致
- 去掉了冗余的while循环和临时变量,直接在一级分组的map遍历中完成二级分组,逻辑更连贯
内容的提问来源于stack exchange,提问作者António Lima
相关产品推荐
相关产品推荐

