2

I have two deeply nested objects containing arrays and objects within those arrays. I'd like to merge those. Using 'lodash' it doesn't recognize my objects within arrays.

I have this:

var defaults = {
    rooms: [
        {
            name: 'livingroom',
            color: 'white'
        },
        {
            name: 'bedroom',
            color: 'red'
        }
    ],
    people: {
        clothes: [
            {
                fabric: 'wool',
                color: 'black'
            },
            {
                fabric: 'jeans',
                color: 'blue'
            }
        ]
    }
}

var specific = {
    people: {
        wigs: [
            {
                shape: 'trump'
            }
        ]
    },
    furniture : {
        foo: 'bar'
    }
}

the result should look like this:

var merged = {
    rooms: [
        {
            name: 'livingroom',
            color: 'white'
        },
        {
            name: 'bedroom',
            color: 'red'
        }
    ],
    people: {
        clothes: [
            {
                fabric: 'wool',
                color: 'black'
            },
            {
                fabric: 'jeans',
                color: 'blue'
            }
        ],
        wigs: [
            {
                shape: 'trump'
            }
        ]
    },
    furniture : {
        foo: 'bar'
    }
}

using lodash

const _ = require('lodash');
console.log(_.merge({}, specific, defaults));

i get

{ people: { wigs: [ [Object] ], clothes: [ [Object], [Object] ] },
  furniture: { foo: 'bar' },
  rooms:
   [ { name: 'livingroom', color: 'white' },
     { name: 'bedroom', color: 'red' } ] }

this is related to:

Merge Array of Objects by Property using Lodash

How to merge two arrays in JavaScript and de-duplicate items

because I don't have a common index or name I'm a bit lost.

5
  • do you need to keep the object, or is it ok to mutate the objects? Commented Mar 1, 2019 at 11:09
  • no need to keep it. Mutation is fine. Commented Mar 1, 2019 at 11:15
  • Lodash's _.merge() works for your case - jsfiddle.net/py4h830d . Look at the brower's console. Commented Mar 1, 2019 at 11:16
  • How to deep merge instead of shallow merge? Commented Mar 1, 2019 at 11:16
  • OriDrori you're right. I'm still new to js and had (only) issues with console.log() :-) However I like the Answer from Nina Scholz as it doesn't require lodash. I hope that's fine if I accept her answer :) Commented Mar 1, 2019 at 12:26

1 Answer 1

2

You could merge specific to defaults by looking at object or arrays.

function merge(a, b) {
    Object.keys(b).forEach(k => {
        if (!(k in a)) {
            a[k] = b[k];
            return;
        }
        if ([a, b].every(o => o[k] && typeof o[k] === 'object' && !Array.isArray(o[k]))) {
            merge(a[k], b[k]);
            return;
        }
        if (!Array.isArray(a[k])) a[k] = [a[k]];
        a[k] = a[k].concat(b[k]);
    });
    return a;
}

var defaults = { rooms: [{ name: 'livingroom', color: 'white' }, { name: 'bedroom', color: 'red' }], people: { clothes: [{ fabric: 'wool', color: 'black' }, { fabric: 'jeans', color: 'blue' }] } },
    specific = { people: { wigs: [{ shape: 'trump' }] }, furniture: { foo: 'bar' } };

[defaults, specific].reduce(merge);

console.log(defaults);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

5 Comments

IIUC, this won't merge primitive properties like number and string no?
it generates an array and pushes a value.
Oh, you're right. I think a[k].push(k) should be a[k].push(b[k]). Also, a separate check for array might be required. If both of the objects have rooms, then it will become a 2D array because of the push
I think this should do it: a[k] = a[k].concat(b[k]);
Thank you Nina and adiga - beautiful :)

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.