假设我有以下两个数组:
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}
];
这两个数组包含不同的值,但是键相似。我需要将此数据聚合到一个包含两个值但唯一的数组中。
在代码中,上面的两个数组应按以下方式聚合:
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}
];
我想知道在两个数组之间聚合数据的最佳方法是什么。
答案 0 :(得分:2)
我可以通过合并两个数组来实现此目的,然后对合并后的数组运行reduce方法。
在reduce中,它首先检查是否存在具有该名称的条目,如果不存在,则将该条目推送到结果数组。如果确实找到了现有条目,则它将创建不存在的任何属性,并添加已经存在的任何数字属性的值。无论您实际使用哪种情况,这都应该足够灵活。
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)
答案 1 :(得分:1)
您可以减少给定的数据并寻找相同的name
,然后进行更新,否则添加一个新对象。
需要
initial
和toBeMerged
中的项目,通过以下方式减少项目
name
中寻找具有相同r
的物品,
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);
答案 2 :(得分:0)
这是我过去处理此问题的方式。
final
数组,其中将包含最终结果。concat
方法合并数组name
属性进行排序,这意味着所有a将按顺序排列,然后是b依此类推。forEach
方法用于遍历连接的排序数组。如果当前元素具有与name
数组的最后一个元素相同的final
属性,则将el
的数字属性添加到final
数组的最后一个元素。否则,将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);
答案 3 :(得分:0)
您可以在reduce的帮助下完成它。
concat
合并两个数组。reduce
的精简数组上,我们检查对象属性是否已经存在于output
中,而不是在现有属性中添加times
和other
添加一个新属性。
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))
答案 4 :(得分:0)
尝试此代码
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);
答案 5 :(得分:0)
在这里,您有一种在要合并的新数组上使用reduce()和findIndex()的方法。如果要合并的新对象已经存在(例如,某个对象的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);
答案 6 :(得分:0)
使用传播运算符,解构,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);