4

I want to be able to merge two objects by adding their values together.

> a
{ "a" : 1, "b" : 3, "d": {"da": 1}}
> b
{ "a" : 1, "c" : 34, "d": {"da": 2} }

I want to obtain :

> { "a" : 2, "b": 3, "c" : 34, "d": {"da": 3} }

I've tried this but it doesn't work :

 function MergeRecursive(obj1, obj2) {
   for (var p in obj2) {
     try {
       // Property in destination object set; update its value.
       if ( obj2[p].constructor==Object ) {
         obj1[p] += MergeRecursive(obj1[p], obj2[p]);

       } else {
             obj1[p] = obj2[p];
       }

     } catch(e) {
       // Property in destination object not set; create it and set its value.
             obj1[p] = obj2[p];
     }
   }
   return obj1;
 }

Any ideas ?

0

3 Answers 3

4

First, let's define an abstract function that applies a func to a combination of two objects, and then use it together with the summation function.

function merge(x, y, fn) {
    var result = {};

    Object.keys(x).forEach(function(k) {
        result[k] = x[k];
    });

    Object.keys(y).forEach(function(k) {
        result[k] = k in x ? fn(x[k], y[k]) : y[k];
    });

    return result;
}

function add(p, q) {
    if(typeof p === 'object' && typeof q === 'object') {
        return merge(p, q, add);
    }
    return p + q;
}

a = { "a" : 1, "b" : 3, "d": {"da": 1}};
b = { "a" : 1, "c" : 34, "d": {"da": 2}};

sum = merge(a, b, add)
document.write('<pre>'+JSON.stringify(sum,0,3));

merge can be also written in a more functional style, like this:

function clone(x) {
    return Object.keys(x).reduce(function(res, k) {
        res[k] = x[k];
        return res;
    }, {});
}

function merge(x, y, fn) {
    return Object.keys(y).reduce(function(res, k) {
        res[k] = k in x ? fn(x[k], y[k]) : y[k];
        return res;
    }, clone(x));
}

If you're fine with the first object being changed, you can skip the clone step and just pass x.

Sign up to request clarification or add additional context in comments.

Comments

1

My attempt

function MergeRecursive(obj1, obj2) {
    var k = Object.keys(obj1), i = 0;
    for (var p in obj2) {
        if(typeof obj1[p] == 'object' && typeof obj2[p] == 'object')
            obj2[p] = MergeRecursive(obj1[p],obj2[p]);
        else if(obj1[p] != null)
            obj2[p] += obj1[p];
        else
            obj2[k[i]] = obj1[k[i]];
        i++;
    }
    return obj2;
}

To use as

MergeRecursive({ "a" : 1, "b" : 3, "d": {"da": 1}},{ "a" : 1, "c" : 34, "d": {"da": 2} })

Comments

0

Create a resultArray to avoid complexity with obj1. Then just add each value in obj1 to the resultArray with the value of obj2 accumulated if the corresponding key in obj2 exists.

Then add each key in obj2 that was not yet added by the first iteration to the resultArray, so that you don't lose the data from obj2.

   function MergeRecursive(obj1, obj2) {
       resultArray = [];
       for (var key in obj1) {
           if ( typeof obj1[key] === 'object') {
               resultArray[key] = MergeRecursive(obj1[p], obj2[p]);
           } else {
               resultArray[key] = obj1[key] + obj2[p] ?? 0;
           }
       }
       for (var key in obj2) {
           if (key in resultArray){
               continue;
           }
           resultArray[key] = obj2[key];
       }
       return resultArray;
     }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.