繁体   English   中英

合并对象数组中具有“相同键”的对象

[英]Merge objects with "same keys" in array of objects

我有一个像这样的对象数组:

const dataset = 
  [ { date: '2018-01', color: 'red',  value1: null, value2: null, value3: 2,    value4: 6    } 
  , { date: '2018-01', color: 'red',  value1: 0,    value2: 4,    value3: null, value4: null } 
  , { date: '2018-02', color: 'red',  value1: null, value2: null, value3: 2,    value4: 10   } 
  , { date: '2018-02', color: 'red',  value1: -9,   value2: 0,    value3: null, value4: null } 
  , { date: '2019-01', color: 'blue', value1: null, value2: null, value3: 10,   value4: 3    } 
  , { date: '2019-01', color: 'blue', value1: -2,   value2: 8,    value3: null, value4: null } 
  , { date: '2019-02', color: 'blue', value1: null, value2: null, value3: 20,   value4: 2    } 
  , { date: '2019-02', color: 'blue', value1: 9,    value2: 7,    value3: null, value4: null } 
  , ...
  ]

而且我要:

const result = 
  [ { date: '2018-01', color: 'red',  value1: 0,  value2: 4, value3: 2,  value4: 6  } 
  , { date: '2018-02', color: 'red',  value1: -9, value2: 0, value3: 2,  value4: 10 } 
  , { date: '2019-01', color: 'blue', value1: -2, value2: 8, value3: 10, value4: 3  } 
  , { date: '2019-02', color: 'blue', value1: 9,  value2: 7, value3: 20, value4: 2  } 
  , ...
  ] 

result包含与dataset相同的信息。
具有相同datecolor记录合并在一起,空值被可用数据替换。

我怎么能做这样的事情? 我不知道

您可以解构datecolor并迭代其余条目。

 const dataset = [{ date: '2018-01', color: 'red', value1: null, value2: null, value3: 2, value4: 6 }, { date: '2018-01', color: 'red', value1: 0, value2: 4, value3: null, value4: null }, { date: '2018-02', color: 'red', value1: null, value2: null, value3: 2, value4: 10 }, { date: '2018-02', color: 'red', value1: -9, value2: 0, value3: null, value4: null }, { date: '2019-01', color: 'blue', value1: null, value2: null, value3: 10, value4: 3 }, { date: '2019-01', color: 'blue', value1: -2, value2: 8, value3: null, value4: null }, { date: '2019-02', color: 'blue', value1: null, value2: null, value3: 20, value4: 2}, { date: '2019-02', color: 'blue', value1: 9, value2: 7, value3: null, value4: null }], result = Object.values(dataset.reduce((r, { date, color, ...rest }) => { const key = [date, color].join('|'); if (!r[key]) r[key] = { date, color }; Object.entries(rest).forEach(([k, v]) => { if ([undefined, null].includes(r[key][k])) r[key][k] = v; }); return r; }, {})); console.log(result);
 .as-console-wrapper { max-height: 100% !important; top: 0; }

您可以使用Array.reduceObject.values来实现预期的结果。

 const dataset = [{date:'2018-01',color:'red',value1:null,value2:null,value3:2,value4:6},{date:'2018-01',color:'red',value1:0,value2:4,value3:null,value4:null},{date:'2018-02',color:'red',value1:null,value2:null,value3:2,value4:10},{date:'2018-02',color:'red',value1:-9,value2:0,value3:null,value4:null},{date:'2019-01',color:'blue',value1:null,value2:null,value3:10,value4:3},{date:'2019-01',color:'blue',value1:-2,value2:8,value3:null,value4:null},{date:'2019-02',color:'blue',value1:null,value2:null,value3:20,value4:2},{date:'2019-02',color:'blue',value1:9,value2:7,value3:null,value4:null},] const mergeData = (data) => { const finalRes = data.reduce((res, obj)=>{ const {date, color} = obj; const key = `${date}_${color}`; res[key] = { ...res[key], ...obj, value1: res[key]?.value1 || obj.value1, value2: res[key]?.value2 || obj.value2, value3: res[key]?.value3 || obj.value3, value4: res[key]?.value4 || obj.value4 } return res; }, {}); return Object.values(finalRes); } console.log(mergeData(dataset))
 .as-console-wrapper { max-height: 100% !important; }

下面是一种通用方法,而不是将解决方案限制为value1value4 还使用Optional Chaining & Nullish coalescing以确保null不会覆盖0

 const dataset = [{date:'2018-01',color:'red',value1:null,value2:null,value3:2,value4:6},{date:'2018-01',color:'red',value1:0,value2:4,value3:null,value4:null},{date:'2018-02',color:'red',value1:null,value2:null,value3:2,value4:10},{date:'2018-02',color:'red',value1:-9,value2:0,value3:null,value4:null},{date:'2019-01',color:'blue',value1:null,value2:null,value3:10,value4:3},{date:'2019-01',color:'blue',value1:-2,value2:8,value3:null,value4:null},{date:'2019-02',color:'blue',value1:null,value2:null,value3:20,value4:2},{date:'2019-02',color:'blue',value1:9,value2:7,value3:null,value4:null},] const mergeData = (data) => { const finalRes = data.reduce((res, {date, color, ...rest}) => { const key = `${date}_${color}`; let newObj = {} Object.keys(rest).forEach(valKey => { newObj = { ...newObj, [valKey]: res[key]?.[valKey] ?? rest[valKey] //check if the corresponding key is present in `res` object and if it's //null or undefined then replace it with the value from the current object //in the loop } }) res[key] = { date, color, ...newObj } return res; }, {}); return Object.values(finalRes); } console.log(mergeData(dataset))
 .as-console-wrapper { max-height: 100% !important; }

我们在dataset上使用reduce
创建一个空的 ( {} ) 对象累加器 ( acc )。
我们使用键date + color
如果该键不存在,我们只需使用当前值 ( cv ) 创建它。
如果是,我们将cvvalue s 添加到它。

之后,我们获取创建的 Object 的值并分配给result

 var dataset = [ {date: '2018-01', color: 'red', value1: null, value2: null, value3: 2, value4: 6}, {date: '2018-01', color: 'red', value1: 0, value2: 4, value3: null, value4: null}, {date: '2018-02', color: 'red', value1: null, value2: null, value3: 2, value4: 10}, {date: '2018-02', color: 'red', value1: -9, value2: 0, value3: null, value4: null}, {date: '2019-01', color: 'blue', value1: null, value2: null, value3: 10, value4: 3}, {date: '2019-01', color: 'blue', value1: -2, value2: 8, value3: null, value4: null}, {date: '2019-02', color: 'blue', value1: null, value2: null, value3: 20, value4: 2}, {date: '2019-02', color: 'blue', value1: 9, value2: 7, value3: null, value4: null} ]; var result=Object.values(dataset.reduce( (acc, cv) => { if(acc[cv.date+cv.color]==undefined) acc[cv.date+cv.color]=cv; else { acc[cv.date+cv.color].value1+=cv.value1; acc[cv.date+cv.color].value2+=cv.value2; acc[cv.date+cv.color].value3+=cv.value3; acc[cv.date+cv.color].value4+=cv.value4; } return acc; },{} )); console.log(result);
 .as-console-wrapper { max-height: 100% !important; top: 0; }

我会首先按datecolordataset的对象进行分组。 然后通过仅覆盖null值( nullundefined )将单个组中的对象合并在一起。

我在下面构建了一个示例,在它们自己的函数中抽象了groupBymergeWith功能。

 const dataset = [ {date: '2018-01', color: 'red', value1: null, value2: null, value3: 2, value4: 6}, {date: '2018-01', color: 'red', value1: 0, value2: 4, value3: null, value4: null}, {date: '2018-02', color: 'red', value1: null, value2: null, value3: 2, value4: 10}, {date: '2018-02', color: 'red', value1: -9, value2: 0, value3: null, value4: null}, {date: '2019-01', color: 'blue', value1: null, value2: null, value3: 10, value4: 3}, {date: '2019-01', color: 'blue', value1: -2, value2: 8, value3: null, value4: null}, {date: '2019-02', color: 'blue', value1: null, value2: null, value3: 20, value4: 2}, {date: '2019-02', color: 'blue', value1: 9, value2: 7, value3: null, value4: null}, ] const result = Array .from( groupBy(({date, color}) => JSON.stringify([date, color]), dataset) .values() ) .map(group => mergeWith((_, a, b) => a ?? b, ...group)); console.log(result); function groupBy(fn, iterable) { const groups = new Map(); for (const item of iterable) { const key = fn(item); if (!groups.has(key)) groups.set(key, []); groups.get(key).push(item); } return groups; } function mergeWith(fn, ...objects) { const merged = Object.create(null); for (const object of objects) { for (const key in object) { if (key in merged) { merged[key] = fn(key, merged[key], object[key]); } else { merged[key] = object[key]; } } } return merged; }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM