# Summing two objects without altering either

Posted on

Problem

In the slow progress of the project that generated my all-but-tumbleweed previous question I’ve needed to make sum-unions (any better term?) of simple objects where key:value is `sizeClass:tally` — I need the union of all `sizeClasses`, summing their values where they’re the same. I came up with this and I wonder whether anyone sees anything terrible about it or has a slicker way.

``````function mashObj(objA,objB) {
var objC = {};
var [ak,av] = deval(objA);
var [bk,bv] = deval(objB);
for (var i=0;i<ak.length;i++) {
objC[ak[i]] = av[i];
}
for (i=0;i<bk.length;i++) {
objC[bk[i]] = (objC[bk[i]] || 0) + bv[i];
}
return objC;
}
function deval(obj) {
var ks = [];
var vs = [];
for (var k in obj) {
ks.push(k);
vs.push(Math.round(obj[k]));
}
return [ks, vs];
}
``````

These functions are purpose-built, plenty of assumption about what’s coming in, so there’s been no attempt at generalizing. I go through `deval()` rather than doing a `for..in` because I also need to preserve the original two objects — I’ve been getting into a lot of trouble with the spooky-manipulation-at-a-distance problem.

By “sum-union” all I mean is that I might have something like:

``````plot1 = {2:4, 5:12, 7:3};
plot2 = {2:1, 4:3, 5:3};
// and what I want to get is
total == {2:5, 4:3, 5:15, 7:3};
``````

I assume that somewhere in math, logic or CS, probably all three, there’s a proper term for this.

Solution

Since you’re using ES2015 destructuring assignments you can use `Set` and spread:

``````function mashObj(a, b) {
var sum = {};
new Set([...Object.keys(a), ...Object.keys(b)])
.forEach(k => sum[k] = Math.round(a[k]||0) + Math.round(b[k]||0));
return sum;
}
``````

Just a few improvement as the code is quite small.

You can shorten your `deval()` to this:

``````function deval(obj) {
var arr = \$.map(obj, function(value) {
return value;
});
return [Object.keys(obj), arr];
}

plot1 = {2:4, 5:12, 7:3};
plot2 = {2:1,4:3,5:3};

console.log(deval(plot1));``````
``<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>``

There is an `Object.keys()` that creates an array of all the keys of an object. Note, there is also an `Object.values()`, which is an experimental technology with little support in all browsers.
In place of that, I used a `map()` as shown in this example Get object values without looping.