简体   繁体   中英

Update object in array from another object in array

In my code I have two arrays, first one contains multiple objects. While the second one is to store serialized form data (mapped to JSON). So both arrays are having identical keys.

What I want to achieve is to update the values of an object in the original array based on the values of an object in new array dynamically, by ID in the object.

Found some examples online but hard to get them to work. Because most of them are showing either one level of objects but I'm working on complex nested objects in the array.

var products = [
    {
        Id: 1,
        Name: 'Product1',
        Attributes: {
            Storage: 'Normal',
            Size: 'Small'
        }
    },
    {
        Id: 2,
        Name: 'Product2',
        Attributes: {
            Storage: 'Normal',
            Size: 'Small'
        }
    }
];

var newData = [
    {
        Id: 2,
        Name: 'French Fries'
    },
    {
        Id: 1,
        Attributes: {
            Size: 'Medium'
        }
    }
];

The expected outcome is the products array now updated with the values from the second array.

Output:
[
    {
        Id: 1,
        Name: 'Product1',
        Attributes: {
            Storage: 'Normal',
            Size: 'Medium'
        }
    },
    {
        Id: 2,
        Name: 'French Fries',
        Attributes: {
            Storage: 'Normal',
            Size: 'Small'
        }
    }
]

You could take a Map for the update items and iterate products .

If an item is found for an update, take a recursive approach and iterate the entries and check if the value is an object, then iterate the nested properties.

If no nested object found update the property.

This works for arrays as well.

 function update(target, source) { Object.entries(source).forEach(([key, value]) => { if (value && typeof value === 'object') { update(target[key] = target[key] || (Array.isArray(value) ? [] : {}), value); } else if (target[key] !== value) { target[key] = value; } }); } var products = [{ Id: 1, Name: 'Product1', Attributes: { Storage: 'Normal', Size: 'Small' } }, { Id: 2, Name: 'Product2', Attributes: { Storage: 'Normal', Size: 'Small' } }], newData = [{ Id: 2, Name: 'French Fries' }, { Id: 1, Attributes: { Size: 'Medium' } }], map = new Map(newData.map(o => [o.Id, o])); products.forEach(o => map.has(o.Id) && update(o, map.get(o.Id))); console.log(products); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

You can create a function which combine nested objects. And then use map() and find() to create combined array of objects.

 var products = [ { Id: 1, Name: 'Product1', Attributes: { Storage: 'Normal', Size: 'Small' } }, { Id: 2, Name: 'Product2', Attributes: { Storage: 'Normal', Size: 'Small' } } ]; var newData = [ { Id: 2, Name: 'French Fries' }, { Id: 1, Attributes: { Size: 'Medium' } } ]; const haveNested = obj => Object.values(obj).some(x => typeof x === "object"); function combine(obj1,obj2){ if(!haveNested(obj1)) return ({...obj1,...obj2}) let res = obj1 for(let key in obj1){ if(typeof obj1[key] === "object"){ res[key] = combine(obj1[key],obj2[key]); } else if(obj2[key]) res[key] = obj2[key] } return res; } const result = products.map(x => { let temp = newData.find(a => a.Id === x.Id); return temp ? combine(x,temp) : x; }) 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