如何在JavaScript中按嵌套对象值分组整理数组?
按嵌套对象多层分组数组的解决方案
给定包含嵌套banner对象的评论数组,需要按banner.lang → banner.format → user的层级分组,把同语言、同格式、同用户的评论归到一起。
你写的代码问题很明确:每次循环都直接给list[comments[i].banner.lang]赋值新数组,完全覆盖了之前的分组结果,根本没做“检查层级是否存在、存在就追加”的操作,所以之前的数据全丢了。
解决方案
用数组的reduce方法来逐步构建嵌套分组结构是最方便的,每一步先检查当前层级是否存在,不存在就初始化,存在就直接追加数据。
先搞一个更实用的嵌套对象结构(后续访问、操作都方便)
const groupedComments = comments.reduce((acc, comment) => { // 拆出分组要用的字段 const { lang, format } = comment.banner; const { user } = comment; // 提取评论的核心数据 const commentData = { id: comment.id, bannerId: comment.bannerId, comment: comment.content }; // 初始化语言层,不存在就建空对象 if (!acc[lang]) { acc[lang] = {}; } // 初始化格式层 if (!acc[lang][format]) { acc[lang][format] = {}; } // 初始化用户层,已存在就直接加评论 if (!acc[lang][format][user]) { acc[lang][format][user] = []; } acc[lang][format][user].push(commentData); return acc; }, {});
输出的结构是这样的,比你期望的数组结构更易访问:
{ "EN": { "300x250": { "John Doe": [ {"id": 1745, "bannerId": 35002, "comment": "lorem ipsum"}, {"id": 1747, "bannerId": 35002, "comment": "test 2222"} ], "Frank Doe": [ {"id": 1750, "bannerId": 35002, "comment": "test 3333"} ] }, "300x600": { "John Doe": [ {"id": 1744, "bannerId": 35004, "comment": "bla bla"} ] } }, "NL": { "970x250": { "Frank Doe": [ {"id": 1746, "bannerId": 35006, "comment": "tesssttt"} ] } } }
转换成你想要的数组包裹结构
如果一定要和你期望的结构完全一致,在上面的结果基础上做个格式转换就行:
const formattedResult = Object.entries(groupedComments).map(([lang, formats]) => { return { [lang]: Object.entries(formats).map(([format, users]) => { return { [format]: Object.entries(users).map(([user, comments]) => { return { [user]: comments }; }) }; }) }; });
输出结果就和你给出的期望结构一模一样了。
关键逻辑说明
reduce是用来累积结果的,每次遍历都往已有的结构里加数据,不会像你原来的代码那样直接覆盖- 每一层级都先判断是否存在,不存在就初始化对应的对象或数组,确保不会出现
undefined的情况 - 用
Object.entries把对象的键值对转成数组,再通过map逐层转换成你要的数组包裹格式
内容的提问来源于stack exchange,提问作者Slicer
相关产品推荐
相关产品推荐

