Omar
Omar

Reputation: 3060

How to merge objects from two arrays

I have two arrays of objects

    let current = [
        {
            categoryId: 18,
            id: 'fire_18',
            test: 'test'
        }, {
            oldItem: "items that dont exist in new array should be deleted"
        }
    ]

    let new_data = [
        {
            id: 'fire_18',
            categoryId: 18,
            test1: 'test1',
        }, {
            newItem: "new items should be added to final"
        }
    ]

I need to merge those so the result is not missing data from current array. The desired result looks like this

    [
        {
            id: 'fire_18',
            categoryId: 18,
            test1: 'test1',
            test: 'test'
        }, {
            newItem: "new items should be added to final"
        }
    ]

Here is my attempt

let current = [
    {
        categoryId: 18,
        id: 'fire_18',
        test: 'test'
    }, {
        oldItem: "items that dont exist in new array should be deleted"
    }
]

let new_data = [
    {
        id: 'fire_18',
        categoryId: 18,
        test1: 'test1',
    }, {
        newItem: "new items should be added to final"
    }
]

console.log(' === Current ==>', current);
console.log(' === New ==>', new_data);

new_data.map(newItem => {
    let currentMatch;
    try { // incase new item newItem.categoryId wont exist
        currentMatch = current.find(c => c.categoryId == newItem.categoryId) || {};
    } catch (error) { // in that case, no need to merge
        currentMatch = {};
    }
    return Object.assign(currentMatch, newItem);
});
console.log(' === Merged ==>', new_data);

the main thing wrong still is test key from the current arr is missing after merge.

Can anyone modify the pen to not delete keys from the current arr?

Upvotes: 0

Views: 88

Answers (5)

Charlie
Charlie

Reputation: 23858

Note that Array.map method returns a new array. You are not logging this merged new array - but one of your old arrays.

Also, you don't need try catch here. You may also note that if the categoryId is undefined, the objects will still match. So, you need a check for that.

let current = [
    {
        categoryId: 18,
        id: 'fire_18',
        test: 'test'
    }, {
        oldItem: "items that dont exist in new array should be deleted"
    }
]

let new_data = [
    {
        id: 'fire_18',
        categoryId: 18,
        test1: 'test1',
    }, {
        newItem: "new items should be added to final"
    }
]



newArray = new_data.map(newItem => {
    let currentMatch;
        
        
     currentMatch = current.find(c => c.categoryId === newItem.categoryId && newItem.categoryId) || {};
  
  
    return Object.assign(currentMatch, newItem);
});
console.log(' === Merged ==>', newArray);

Upvotes: 1

A. Meshu
A. Meshu

Reputation: 4148

I found this. On your code it goes like that:

let current = [
    {
        categoryId: 18,
        id: 'fire_18',
        test: 'test'
    }, {
        oldItem: "items that dont exist in new array should be deleted"
    }
]

let new_data = [
    {
        id: 'fire_18',
        categoryId: 18,
        test1: 'test1',
    }, {
        newItem: "new items should be added to final"
    }
]

function merge(a, b, prop){
  var reduced = a.filter(function(aitem){
      return ! b.find(function(bitem){
          return aitem[prop] === bitem[prop];
      });
  });
  return reduced.concat(b);
}
console.log(merge(current, new_data, "id") );

Upvotes: 0

Milind Agrawal
Milind Agrawal

Reputation: 2944

You can use es6 spread operator to meet your requirement

  var current = [{
    categoryId: 18,
    id: 'fire_18',
    name: 'Servers',
    slugName: 'fire_18',
    test: 'test'
}]

var new_data = [{
    id: 'fire_18',
    categoryId: 18,
    name: 'Servers',
    slugName: 'fire_18'
}]

const results = new_data.map(item => {
    let newItem = { ...item };
    const currentMatchItem = current.find(c => c.categoryId == newItem.categoryId);

    if (currentMatchItem) {
        newItem = { ...currentMatchItem, ...newItem };
    }

    return newItem;
});

console.log(results);

Upvotes: 0

ray
ray

Reputation: 27285

Like this? I'm not sure what you're expecting to happen with the newItem and oldItem entries.

let current = [{
  categoryId: 18,
  id: 'fire_18',
  test: 'test'
}]

let new_data = [{
  id: 'fire_18',
  categoryId: 18,
  test1: 'test1',
}]

const result = Object.values([...current, ...new_data].reduce((acc, {
  categoryId,
  ...other
}) => ({
  ...acc,
  [categoryId]: {
    categoryId,
    ...other
  }
}), {}));

console.log(result);

Upvotes: 0

Sagar Chaudhary
Sagar Chaudhary

Reputation: 1403

You can use lodash for this.

finalArr = _(_.flatten([current, new_data]))
                                        .groupBy('id')
                                        .map(_.spread(_.assign))
                                        .value();

Upvotes: 0

Related Questions