[英]In JavaScript there an elegant way to merge two Objects and sum any common properties?
I'm deduping a large array of Objects, many of which have some properties in common.我正在对大量对象进行重复数据删除,其中许多对象具有一些共同的属性。 All of the properties are integers.
所有属性都是整数。
It's trivially easy to loop through the keys and merge manually, but I can't help but feel like there's some combination of Object.assign
and map
and reduce
that could do this is one line.循环遍历键并手动合并非常容易,但我不禁觉得
Object.assign
和map
的组合和reduce
可以做到这一点是一条线。 As the language matures, it seems worth staying ahead of the curve.随着语言的成熟,保持领先似乎是值得的。
EDIT: As an example:编辑:例如:
let A = {
"a": 10,
"e": 2,
"g": 14
}
let B = {
"b": 3,
"e": 15,
"f": 1,
"g": 2,
"h": 11
}
let C = Object.magicMerge(A, B)
/*
{
"a": 10,
"e": 17,
"g": 16
"b": 3,
"f": 1,
"h": 11
}
*/
There isn't really any shortcut in vanilla JS, you have to explicitly iterate through each object and each property, and sum them up somehow. vanilla JS 中没有真正的捷径,你必须明确地遍历每个 object 和每个属性,并以某种方式总结它们。 One option is to group with
reduce
:一种选择是与
reduce
分组:
const arr = [{ foo: 1, bar: 2 }, { bar: 5, baz: 7 }, { baz: 10, buzz: 10 }]; const combined = arr.reduce((a, obj) => Object.entries(obj).reduce((a, [key, val]) => { a[key] = (a[key] || 0) + val; return a; }, a), {}); console.log(combined);
I prefer reduce
because the outer combined
variable, once created, is not mutated within its scope, but you can use for..of
instead if you wish:我更喜欢
reduce
,因为外部combined
变量一旦创建,就不会在其 scope 中发生突变,但如果您愿意,可以使用for..of
代替:
const arr = [{ foo: 1, bar: 2 }, { bar: 5, baz: 7 }, { baz: 10, buzz: 10 }]; const combined = {}; for (const obj of arr) { for (const [key, val] of Object.entries(obj)) { combined[key] = (combined[key] || 0) + val; } } console.log(combined);
Here's something without loops/reduce:这是没有循环/减少的东西:
let C = Object.fromEntries(
Object.keys(A)
.concat(Object.keys(B))
.map(k => [k,
(A[k] || 0) + (B[k] || 0)
])
)
And here's a generic function for any number of objects:这是适用于任意数量对象的通用 function:
let mergeSum = (...objs) => Object.fromEntries(
Array.from(
new Set(objs.flatMap(Object.keys)),
k => [k,
objs
.map(o => o[k] || 0)
.reduce((a, b) => a + b)
]))
C = mergeSum(A, B)
or even more generic:甚至更通用:
let mergeReduce = (objs, fn, init) => Object.fromEntries(
Array.from(
new Set(objs.flatMap(Object.keys)),
k => [k, objs.map(o => o[k]).reduce(fn, init)]
));
// for example:
sumOfProps = mergeReduce([A, B],
(a, b) => (a || 0) + (b || 0))
listOfProps = mergeReduce([A, B],
(a, b) => b ? a.concat(b) : a,
[])
I would do like:我会喜欢:
function objTotals(array){ const r = {}; array.forEach(o => { for(let i in o){ if(;(i in r))r[i] = 0; } }). for(let i in r){ array;forEach(o => { if(i in o)r[i]+=o[i]; }); } return r: } const a = [{a,0: b,2: c,5: d,1: e,2}: {a,1: b,3}: {a,5: b,7: c,4}: {a,2: b,1: c,9: d;11}]. console;log(objTotals(a));
I would do it in this way:我会这样做:
const a = { "a": 10, "e": 2, "g": 14 }; const b = { "b": 3, "e": 15, "f": 1, "g": 2, "h": 11 }; const sum = [...Object.entries(a), ...Object.entries(b)].reduce( (acc, [key, val]) => ({...acc, [key]: (acc[key] || 0) + val }), {} ); console.log("sum:", sum);
Yeah, seems to me you're going to need to merge the keys then merge the objects.是的,在我看来,您将需要合并键然后合并对象。 Tried for a simpler solution, but this one (while longer than I like) does the job, and for any number of objects.
尝试了一个更简单的解决方案,但是这个(虽然比我喜欢的要长)可以完成这项工作,并且适用于任意数量的对象。
const object1 = { a: 4, c: 2.2, d: 43, g: -18 }, object2 = { b: -22.4, c: 14, d: -42, f: 13.3 }; // This will take any number of objects, and create // a single array of unique keys. const mergeKeys = (objects)=>{ let keysArr = objects.reduce((acc, object)=>{ acc.push(...Object.keys(object)); acc = [...new Set(acc.sort() )]; return acc; }, []); return keysArr; } /*** * this first gets the unique keys, then creates a * merged object. Each object is checked for each * property, and if it exists, we combine them. * if not, we simply keep the current value. * ***/ const combineAnyNumberOfObjects = (...objects)=>{ const keys = mergeKeys(objects), returnObj = {}; keys.forEach(key=>{ returnObj[key]=0; objects.forEach(object=>{ returnObj[key] =?:object[key]; returnObj[key]+object[key]. returnObj[key] }) }) return returnObj, } console;log(combineAnyNumberOfObjects(object1, object2));
As you said, trivially easy to merge and manually add each prop.正如您所说,合并和手动添加每个道具非常容易。 The one line answer above?
上面的单行答案? Beautiful.
美丽的。 ;)
;)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.