简体   繁体   中英

Merge two deep arrays

So I've got two infinitely deep arrays as seen below.

const one = [
    {
        name: 'CRISPS',
        items: [
            {
                name: 'salty crisps',
                items: []
            }
        ]
    },
    {
        name: 'CHOCOLATE',
        items: [
            {
                name: 'full sized bars',
                items: []
            }
        ]
    }
]

const two = [
    {
        name: 'CRISPS',
        items: [
            {
                name: 'salty crisps',
                items: []
            }
        ]
    },
    {
        name: 'DRINKS',
        items: [
            {
                name: 'fizzy drinks',
                items: []
            }
        ]
    },
    {
        name: 'CHOCOLATE',
        items: [
            {
                name: 'small sized bars',
                items: []
            }
        ]
    }
]

I would like to be able to merge them so that I will get the outcome of

const three = [
    {
        name: 'CRISPS',
        items: [
            {
                name: 'salty crisps',
                items: []
            }
        ]
    },
    {
        name: 'CHOCOLATE',
        items: [
            {
                name: 'full sized bars',
                items: []
            },
            {
                name: 'small sized bars',
                items: []
            }
        ]
    },
    {
        name: 'DRINKS',
        items: [
            {
                name: 'fizzy drinks',
                items: []
            }
        ]
    }
]

This merge will be the combination of the two arrays as well as only keeping the unique values of the items in the list.

I have an inclining that I will need to create a custom recursive function to merge these two, however I was hoping that there might be a premade solution to do this.

I've attempted with lodash's _.merge() However I was either using it wrong or it is not applicable.

Edit For lodash I attempted the standard _.merge(one, two) however this tended to not merge deeply. From there I've started looking at creating my own recursive method.

I've also updated the example to how how CHOCOLATE should merge.

Thanks!

You're right, a recursive function is the way to go. The idea is that we merge the lists at the top level, and if we find things to merge in one AND two , we recursively call merge on THEIR items:

 function merge(arr1, arr2) { let res = []; let arr2Index = arr2.reduce((acc, curr) => { acc[curr.name] = curr; return acc; }, {}); // add all elements from arr1 to res after merging them with their common element in arr2 arr1.forEach(i => { if (i.name in arr2Index) { i.items = merge(i.items, arr2Index[i.name].items); delete arr2Index[i.name]; } res.push(i); }); // add remaining objects from arr2 to res res.push(...Object.values(arr2Index)); return res; } // Test const one = [{ name: 'CRISPS', items: [{ name: 'salty crisps', items: [{ name: 'very salty crisps', items: [{ name: 'mega salty crisps', items: [] }] }] }] }, { name: 'CHOCOLATE', items: [{ name: 'full sized bars', items: [] }] } ]; const two = [{ name: 'CRISPS', items: [{ name: 'salty crisps', items: [{ name: 'very salty crisps', items: [{ name: 'hi', items: [{ name: 'somewhat salty crisps', items: [] }] }] }] }] }, { name: 'DRINKS', items: [{ name: 'fizzy drinks', items: [] }] } ]; console.log(merge(one, two)); 

Try this method using spread operator:

 const one = [ { name: 'CRISPS', items: [{ name: 'salty crisps',items: [] }] }, { name: 'CHOCOLATE', items: [{ name: 'full sized bars', items: [] }] } ] const two = [ { name: 'CRISPS', items: [{ name: 'salty crisps',items: [] }] }, { name: 'DRINKS', items: [{ name: 'fizzy drinks',items: [] }] } ] const merge = (p, ...arrs) => [...new Set([].concat(...arrs).map(a => JSON.stringify(a)))].map(a => JSON.parse(a)); const three = merge('name', one, two); console.log(three); 

thanks to this post: https://gist.github.com/yesvods/51af798dd1e7058625f4

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