如何用JavaScript按metadata.id合并对象并实现tests属性求和?
使用reduce合并数组中metadata.id重复的对象
输入数据
let input = { "data": [ {"state": "CA","tests": 12,"city": [ "Mountain View"],"metadata": { "id": 15 }}, {"state": "TX","tests": 10,"city": [ "Austin" ],"metadata": { "id": 15 }}, {"state": "AZ","tests": 5,"city": [ "Flagstaff" ],"metadata": { "id": 10 }} ] }
合并需求
将metadata.id相同的对象合并:
state和city属性拼接为数组(单个元素时state用字符串,多个元素时保留数组)tests属性求和metadata保留原对象
预期输出
let result = { "data": [ {"state": ["CA", "TX"],"tests": 22,"city": ["Mountain View", "Austin"],"metadata": { "id": 15 }}, {"state": "AZ","tests": 5,"city": [ "Flagstaff" ],"metadata": { "id": 10 }} ] }
我的尝试代码
我用reduce实现时,无法正确完成tests属性累加,代码如下:
let total_tests = 0; let res = [{ data: Object.values(input[0].data.reduce((acc, {state, city, metadata, tests, category}) => { const id = metadata?.id; if (!acc[id]) { acc[id] = {id,state: [],city: [],metadata,tests,category} } acc[id].state.push(state) acc[id].city.push(...city) acc[id].tests = total_tests + acc[id].tests; return acc }, {})) }]
正确实现方案
问题出在使用全局变量total_tests累加,导致所有id的tests共用同一个值,且初始化时直接赋值当前对象的tests,未做累加逻辑。修正后的代码如下:
const result = { data: Object.values(input.data.reduce((acc, item) => { const id = item.metadata.id; // 初始化当前id的合并对象 if (!acc[id]) { acc[id] = { state: [], city: [], tests: 0, metadata: item.metadata }; } // 累加tests acc[id].tests += item.tests; // 收集state acc[id].state.push(item.state); // 展开city数组添加 acc[id].city.push(...item.city); return acc; }, {})).map(mergedItem => { // 单个state转为字符串,匹配预期输出格式 mergedItem.state = mergedItem.state.length === 1 ? mergedItem.state[0] : mergedItem.state; return mergedItem; }) };
核心修正说明:
- 移除全局变量
total_tests,每个id的tests单独维护,初始设为0,每次循环累加当前项的tests - 修正原代码中
input[0].data的错误,直接取input.data - 通过
map处理state格式,单个元素转为字符串,多个元素保留数组 - 移除原代码中未用到的
category属性,避免冗余
内容的提问来源于stack exchange,提问作者Aren Trot
相关产品推荐
相关产品推荐

