简体   繁体   中英

How to merge two nested objects in javascript based on the keys of the destination object?

I have two objects, one can be considered a superset and the other a subset. The subset is guaranteed to have similar structure as the superset except that the subset will be missing some properties from the superset.

var superset = {
    car: {
        type: 'SUV',
        brand: 'Volvo',
        color: 'Black'
    },
    features: {
        interior: {
            seats: 'leather',
            color: 'black'
        },
        exterior: {
            windows: 'tinted'
        },
        doors: 5
    },
    warranty: '5 yrs'
}

var subset = {
    car: {
        type: true,
        brand: true        
    },
    features: {
        interior: {
            seats: true            
        },
        exterior: {
            windows: true
        },
        doors: true
    }
}

I want to merge these two objects, using the values from the superset but only for the properties present in the subset. The result should look like below:

{
    car: {
        type: 'SUV',
        brand: 'Volvo'
    },
    features: {
        interior: {
            seats: 'leather'
        },
        exterior: {
            windows: 'tinted'
        },
        doors: 5
    }
}

mergeWith from Lodash almost does the job but it only seems to work for the first level of properties like below. Idea is that, once I assign a unique value to all the unwanted properties, I can loop through and get rid of them later.

_.mergeWith(subset, superset, function(a, b) {return a ? b : 'DELETE'})

Result:
{
    car: {
        type: 'SUV',
        brand: 'Volvo',
        color: 'Black'
    },
    features: {
        interior: {
            seats: 'leather',
            color: 'black'
        },
        exterior: {
            windows: 'tinted'
        },
        doors: 5
    },
    warranty: 'DELETE'
}

Any assistance is appreciated.

This solution simply walks the subset (which I call schema ) and copies values from the superset (which I call input ) if they exist. If a value is an object in both of them, the function calls itself to process the nested properties:

 function merge(input, schema) { var result = {} for (var k in schema) { if (input[k] && typeof input[k] === 'object' && schema[k] && typeof schema[k] === 'object') { result[k] = merge(input[k], schema[k]) } else if (k in input) { result[k] = input[k] } } return result } var superset = { car: { type: 'SUV', brand: 'Volvo', color: 'Black' }, features: { interior: { seats: 'leather', color: 'black' }, exterior: { windows: 'tinted' }, doors: 5 }, warranty: '5 yrs' } var subset = { car: { type: true, brand: true }, features: { interior: { seats: true }, exterior: { windows: true }, doors: true } } var result = merge(superset, subset) console.log(result)

A simple recursive function that runs through the object with the wanted keys and if each exists in the data object (the superset) then either assigns the value to result if it is not an object, otherwise calls itself to do exactly the same for the subobject at that position. It can also be improved to return an error if the keys object is malformed, ie if it contains a key that is not anywhere in the superset.

var superset = {
    car: {
        type: 'SUV',
        brand: 'Volvo',
        color: 'Black'
    },
    features: {
        interior: {
            seats: 'leather',
            color: 'black'
        },
        exterior: {
            windows: 'tinted'
        },
        doors: 5
    },
    warranty: '5 yrs'
};

var subset = {
    car: {
        type: true,
        brand: true        
    },
    features: {
        interior: {
            seats: true            
        },
        exterior: {
            windows: true
        },
        doors: true
    }
};


var merge = function(data, keys_obj, result)
{
    for (key in keys_obj)
    {
        if (data.hasOwnProperty(key))
        {
            if (typeof(data[key]) == "object")
            {
                result[key] = {};
                merge(data[key], keys_obj[key], result[key]);
            }
            else if (data[key])
                result[key] = data[key];
        }
        //else you can throw an exception here: malformed subset
    }
};

function test()
{
    var result = {};
    merge(superset, subset, result);

    console.log(result);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM