如何用JavaScript按ID分组对象并拼接state、city属性?
问题:合并相同metadata.id的对象并拼接属性
我想用reduce方法实现一个遍历逻辑,但没成功。需求是:输入是包含data数组的对象,数组里部分对象的metadata.id重复,要把相同id的对象合并成一个,同时拼接state和city属性。下面是输入、期望输出和我尝试的代码,求正确实现方法。
输入示例
let input = { "data": [ { "state": "CA", "city": [ "Mountain View"], "metadata": { "id": 15 }, }, { "state": "TX", "city": [ "Austin" ], "metadata": { "id": 15 }, }, { "state": "AZ", "city": [ "Flagstaff" ], "metadata": { "id": 10 }, }, ], }
期望输出示例
let result = { "data": [ { "state": ["CA", "TX"], "city": ["Mountain View", "Austin"], "metadata": { "id": 15 }, }, { "state": "AZ", "city": [ "Flagstaff" ], "metadata": { "id": 10 }, }, ], }
我尝试的代码
let result = Object.values(input?.data?.reduce((acc, {state, city, metadata}) => { if (!acc[metadata?.id]) { acc[metadata?.id] = { id }; } acc[metadata?.id].state = acc[metadata?.id].state.concat(state); acc[metadata?.id].city = acc[metadata?.id].city.concat(city); return acc; }, {}));
正确实现方法
你的代码存在几个问题:初始化对象时结构错误、未处理state初始非数组导致的concat报错,且最终结果未包装成{ data: [...] }的结构。以下是精准实现:
const result = { data: Object.values(input.data.reduce((acc, item) => { const id = item.metadata.id; // 初始化分组对象 if (!acc[id]) { acc[id] = { state: [item.state], // 先统一存为数组,后续处理格式 city: [...item.city], metadata: { ...item.metadata } }; } else { // 合并state和city acc[id].state.push(item.state); acc[id].city = acc[id].city.concat(item.city); } return acc; }, {})).map(mergedItem => ({ ...mergedItem, // 处理state格式:单个值转为字符串,多个保留数组 state: mergedItem.state.length === 1 ? mergedItem.state[0] : mergedItem.state })) };
关键说明:
- 用
metadata.id作为分组键,通过reduce将相同id的对象聚合 - 初始化时统一将state存为数组,避免后续合并时的类型错误
- 最后通过map调整state的格式,匹配期望输出(单个值为字符串,多个为数组)
- 保留原对象的metadata结构,避免引用问题
内容的提问来源于stack exchange,提问作者Aren Trot
相关产品推荐
相关产品推荐

