[英]Aggregate two arrays of objects
Let's say I've got these two arrays: 假设我有这两个数组:
const initial: Array<GivenObj> = [
{name: 'a', times: 40, other: 50},
{name: 'b', times: 10, other: 15},
{name: 'c', times: 15, other: 12}
];
const toBeMerged: Array<GivenObj> = [
{name: 'a', times: 45, other: 30},
{name: 'c', times: 10, other: 10},
{name: 'd', times: 23, other: 10}
];
These two arrays contain different values, but similar keys. 这两个数组包含不同的值,但类似的键。 I need to aggregate this data to a single array that will contain both of their values, but uniquely.
我需要将这些数据聚合到一个包含其两个值的唯一数组中。
In code, the two arrays above should be aggregated as follows: 在代码中,上面的两个数组应该聚合如下:
const aggregated: Array<GivenObj> = [
{name: 'a', times: 85, other: 80},
{name: 'b', times: 10, other: 15},
{name: 'c', times: 25, other: 22},
{name: 'd', times: 23, other: 10}
];
I was wondering what's the best way to aggregate data between two arrays. 我想知道在两个数组之间聚合数据的最佳方法是什么。
I'd approach this by merging the two arrays, then running a reduce against that combined array. 我通过合并两个数组,然后对该组合数组运行reduce来解决这个问题。
Inside the reduce, it first checks to see if an entry with that name exists, if not it pushes that entry to the result array. 在reduce中,它首先检查是否存在具有该名称的条目,如果不存在,则将该条目推送到结果数组。 If it does find an existing entry, it creates any property that doesn't exist, and adds the values of any numerical properties that already exist.
如果确实找到了现有条目,则会创建任何不存在的属性,并添加已存在的任何数字属性的值。 This should be flexible enough for whatever your actual use case is.
无论您的实际用例如何,这都应该足够灵活。
const initial = [ {name: 'a', times: 40, other: 50}, {name: 'b', times: 10, other: 15}, {name: 'c', times: 15, other: 12} ]; const toBeMerged = [ {name: 'a', times: 45, other: 30}, {name: 'c', times: 10, other: 10}, {name: 'd', times: 23, other: 10} ]; const result = [ ...initial, ...toBeMerged ].reduce((arr, t) => { let existing = arr.filter(x => x.name == t.name)[0] if(!existing) arr.push(t) else { const keys = Object.keys(t) keys.forEach(key => { if(!existing.hasOwnProperty(key)) existing[key] = t[key] else if(typeof existing[key] === "number") existing[key] += t[key] }) } return arr }, []) console.log(result)
You could reduce the given data and look for same name
, then update, otherwise add a new object. 您可以减少给定数据并查找相同的
name
,然后更新,否则添加新对象。
It takes 它需要
initial
and toBeMerged
, initial
和toBeMerged
项的新数组, reducing the items by 减少项目
name
in the accumulator r
, r
寻找具有相同name
的项目, const initial = [{ name: 'a', times: 40, other: 50 }, { name: 'b', times: 10, other: 15 }, { name: 'c', times: 15, other: 12 }], toBeMerged = [{ name: 'a', times: 45, other: 30 }, { name: 'c', times: 10, other: 10 }, { name: 'd', times: 23, other: 10 }], merged = [...initial, ...toBeMerged].reduce((r, o) => { var temp = r.find(p => o.name === p.name); if (!temp) return [...r, { ...o }]; temp.times += o.times; temp.other += o.other; return r; }, []); console.log(merged);
Here is how I have approached this problem in the past. 以下是我过去处理此问题的方法。
final
array, which will contain the final result. final
数组,其中包含最终结果。 concat
method concat
方法合并数组 name
property, meaning that all the a's will be in order, then the b's, etc. name
属性排序,这意味着所有的a将按顺序排列,然后是b,等等。 forEach
method is used to iterate through the concatenated, sorted array. forEach
方法用于遍历连接的排序数组。 If the current element has the same name
property as the last element of the final
array, then add the numeric properties of el
to the last element of the final
array. final
数组的最后一个元素具有相同的name
属性,则将el
的数字属性添加到final
数组的最后一个元素。 Otherwise, add el
to the end of the final array. el
添加到最终数组的末尾。 const initial = [ {name: 'a', times: 40, other: 50}, {name: 'b', times: 10, other: 15}, {name: 'c', times: 15, other: 12} ]; const toBeMerged = [ {name: 'a', times: 45, other: 30}, {name: 'c', times: 10, other: 10}, {name: 'd', times: 23, other: 10} ]; let final = []; initial.concat(toBeMerged).sort((a, b) => a.name > b.name).forEach(el => { if (final.length > 0 && el.name === final[final.length - 1].name) { final[final.length - 1].times += el.times; final[final.length - 1].other += el.other; } else { final.push(el); } }) console.log(final);
You can do it with help of reduce . 你可以在减少的帮助下做到这一点。
concat
. concat
合并数组。 reduce
we check if the object property is already present in output
than we add times
and other
in existing property if not than we add a new property. reduce
的concated数组上,我们检查对象属性是否已经存在于output
不是我们在现有属性中添加other
times
,如果不是我们添加新属性。 const initial= [{name: 'a', times: 40, other: 50},{name: 'b', times: 10, other: 15},{name: 'c', times: 15, other: 12}]; const toBeMerged= [{name: 'a', times: 45, other: 30},{name: 'c', times: 10, other: 10},{name: 'd', times: 23, other: 10}]; let temp = initial.concat(toBeMerged) let op = temp.reduce((output,current)=>{ if( output[current.name] ){ output[current.name].times += current.times output[current.name].other += current.other } else{ output[current.name] = current; } return output; },{}) console.log(Object.values(op))
Try this code 试试这个代码
const initial = [ {name: 'a', times: 40, other: 50}, {name: 'b', times: 10, other: 15}, {name: 'c', times: 15, other: 12} ]; const toBeMerged = [ {name: 'a', times: 45, other: 30}, {name: 'c', times: 10, other: 10}, {name: 'd', times: 23, other: 10} ]; //console.log(initial); function arrayUnique(array) { var a = array.concat(); for(var i=0; i<a.length; ++i) { for(var j=i+1; j<a.length; ++j) { if(a[i].name === a[j].name) { a[i].times +=a[j].times; a[i].other +=a[j].other; a.splice(j--, 1); } } } return a; } // Merges both arrays and gets unique items var array = arrayUnique(initial.concat(toBeMerged)); console.log(array);
Here you have one approach using reduce() and findIndex() over the new array to be merged. 在这里,你有一种方法使用reduce()和findIndex()来合并新的数组。 If a new object to be merged already exists (ie the
name
property match for some object), we increment the rest of the matching properties and add the non-existing ones, otherwise we push the entire new object: 如果已经存在要合并的新对象(即某个对象的
name
属性匹配),我们会增加其余的匹配属性并添加不存在的属性,否则我们将推送整个新对象:
const initial = [ {name: 'a', times: 40, other: 50}, {name: 'b', times: 10, other: 15}, {name: 'c', times: 15, other: 12} ]; const toBeMerged = [ {name: 'a', times: 45, other: 30, another: 76}, {name: 'c', times: 10, other: 10}, {name: 'd', times: 23, other: 10} ]; let newArray = toBeMerged.reduce((res, curr) => { let found = res.findIndex(x => x.name === curr.name); if (found >= 0) { res[found] = Object.keys(curr).reduce((r, c) => { r[[c]] = (r[[c]] && c !== 'name') ? r[[c]] + curr[[c]] : curr[[c]]; return r; }, res[found]); } else { res.push(curr); } return res; }, initial); console.log(newArray);
Using spread operator, destructuring, Array#reduce, Object#values and Map 使用扩展运算符,解构,Array#reduce,Object#values和Map
const initial=[{name:'a',times:40,other:50},{name:'b',times:10,other:15},{name:'c',times:15,other:12}];const toBeMerged=[{name:'a',times:45,other:30},{name:'c',times:10,other:10},{name:'d',times:23,other:10}] const res = [...[...initial, ...toBeMerged] .reduce((a,{name,times,other})=>{ const b = a.get(name); return a.set(name,{name, times: (b?b.times:0) + times, other: (b?b.other:0) + other}); }, new Map()).values()]; console.log(res);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.