Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating Javascript object recursively

I have an nested object that I want to update it with values provided by object that contains similar structure but only the properties that I want updated. Creating a new result instead of modifying the initial objects is great too.

    var initial = 
      { 
         a: 1, 
         b : { 
            c : 2, 
            d : 3 
         },
         f: 5 
      }; 

    var update = {
        a: 2,
        b: {
           d: 2
        }
    };         
    function updateFunction (a,b) {  return a+b;};
    var result= 
      { 
         a: 3, // updateFunction (1,2)=> 3
         b : { 
            c : 2, 
            d :5 // updateFunction (3,2) => 5
         },
         f: 5 
      };  
like image 374
slobodan.blazeski Avatar asked May 05 '13 11:05

slobodan.blazeski


2 Answers

Have not tested fully, but maybe,

assuming objects are simple as stated,

function updateFunction (a,b) {  return a + b;};    

function recurse(initial, update){
    for(prop in initial){
        if({}.hasOwnProperty.call(initial, prop) && {}.hasOwnProperty.call(update, prop)){
            if(typeof initial[prop] === 'object' && typeof update[prop] === 'object'){
                recurse(initial[prop], update[prop]);
            }
            else{
                initial[prop] = updateFunction(initial[prop], update[prop]);
            }
        }
    }
}
recurse(initial, update);

EDIT

If result is expected without changing initial

function updateFunction (a,b) {  return a + b;};

function recurse(initial, update){
    var result = {};
    for(prop in initial){
        if({}.hasOwnProperty.call(initial, prop)){
            result[prop] = initial[prop];    
            if({}.hasOwnProperty.call(update, prop)){
                if(typeof initial[prop] === 'object' && typeof update[prop] === 'object'){
                    result[prop] = recurse(initial[prop], update[prop]);
                }
                else{
                    result[prop] = updateFunction(initial[prop], update[prop]);
                }
            }
        }    
    }
    return result;
}
var result = recurse(initial, update);

hope this helps.

like image 126
shakib Avatar answered Nov 17 '22 14:11

shakib


Here's how I'd do it:

// The parallel to Array.map
Object.map = function(obj, f) {
    var result = {};
    for(k in obj)
        if({}.hasOwnProperty.call(obj, k))
            result[k] = f(k, obj[k]);
    return result;
}

// Takes two objects and uses `resolve` to merge them
function merge(a, b, resolve) {
    return Object.map(a, function(k, a_value) {
        if(k in b)
            return resolve(a_value, b[k]);
        else
            return a_value;
    });
}

// same as above, but recursing when an object is found
function recursive_merge(a, b, resolve) {
    return merge(a, b, function(a_value, b_value) {
        if(typeof a_value == 'object' && typeof b_value == 'object')
            return recursive_merge(a_value, b_value, resolve);
        else
            return resolve(a_value, b_value);
    });
}

result = recursive_merge(initial, update, function(a, b) { return a + b; })
like image 3
Eric Avatar answered Nov 17 '22 15:11

Eric