如何用JavaScript高效转换JSON结构?请求排查代码问题
解决JSON数组按分类合并子分类的问题
首先咱们先看看你现有代码的问题:
你用forEach遍历每一项的时候,每次都新建了一个category对象并直接push到dataArr里,完全没做「判断当前分类是否已经存在」的操作。所以原来的4条数据会生成4个独立的对象,自然没法把同分类的子项合并到一起啦。
接下来给你一个高效的实现方式,用Array.reduce()来做分组合并,这是处理这类结构转换的常用方法:
let result = [ { "category": "Social Media", "category_id": 6, "sub_category": "Facebook", "sub_category_id": 5 }, { "category": "Social Media", "category_id": 6, "sub_category": "Instagram", "sub_category_id": 7 }, { "category": "Tech", "category_id": 3, "sub_category": "Angular", "sub_category_id": 1 }, { "category": "Tech", "category_id": 3, "sub_category": "Javascript", "sub_category_id": 6 } ]; // 用reduce进行分组合并 const mergedResult = result.reduce((acc, current) => { // 先根据category_id查找是否已经存在该分类 const existingCategory = acc.find(item => item.category_id === current.category_id); if (existingCategory) { // 如果存在,就把当前子分类push到对应的sub_category数组里 existingCategory.sub_category.push({ sub_category: current.sub_category, sub_category_id: current.sub_category_id }); } else { // 如果不存在,就新建一个分类对象,把当前子分类作为初始项 acc.push({ category: current.category, category_id: current.category_id, sub_category: [{ sub_category: current.sub_category, sub_category_id: current.sub_category_id }] }); } return acc; }, []); // 初始值是空数组 console.log(mergedResult);
代码逻辑说明:
reduce的第一个参数是累积函数,acc是我们最终要生成的结果数组,current是当前遍历到的元素。- 每次遍历先检查
acc里是否已经存在相同category_id的分类:- 存在的话,直接把当前子分类追加到它的
sub_category数组中; - 不存在的话,创建一个新的分类对象,把当前子分类作为
sub_category的初始元素,再加入到acc里。
- 存在的话,直接把当前子分类追加到它的
- 最后返回累积的结果数组,就是你想要的嵌套结构啦。
如果你的数据量很大,用find可能效率稍低,可以优化成用对象做映射(以category_id为键),最后再把对象的值转成数组,这样查找的时间复杂度是O(1),更高效:
const mergedResult = Object.values(result.reduce((map, current) => { const id = current.category_id; if (!map[id]) { map[id] = { category: current.category, category_id: id, sub_category: [] }; } map[id].sub_category.push({ sub_category: current.sub_category, sub_category_id: current.sub_category_id }); return map; }, {}));
这个版本先用对象做中间映射,避免了每次find的遍历,数据量大的时候性能会更好~
内容的提问来源于stack exchange,提问作者Sangram Badi
相关产品推荐
相关产品推荐

