0

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?

Omar
  • 2,726
  • 2
  • 32
  • 65
  • 4
    I've gone ahead and edited your question to include your attempt as a snippet in the question itself, as opposed to an external link. In the future, please make sure all necessary code is *in the question itself*. Users shouldn't have to visit a second website to see the complete question :) – Tyler Roper Sep 19 '19 at 19:39
  • Where did `name` and `slugName` come from in your expected results? – Maria Sep 19 '19 at 19:43
  • @Maria it was old irrelevant data from a prev version. I edited my question to reflect more accurately. – Omar Sep 19 '19 at 19:45
  • 1
    Are `newItem` and `oldItem` actually in the data? – ray Sep 19 '19 at 19:45
  • Please refer to this https://stackoverflow.com/questions/19480008/javascript-merging-objects-by-id – Milind Agrawal Sep 19 '19 at 19:48

5 Answers5

1

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);
Charlie
  • 22,886
  • 11
  • 59
  • 90
0

You can use lodash for this.

finalArr = _(_.flatten([current, new_data]))
                                        .groupBy('id')
                                        .map(_.spread(_.assign))
                                        .value();
Sagar Chaudhary
  • 1,343
  • 7
  • 21
0

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);
ray
  • 26,557
  • 5
  • 28
  • 27
0

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);
Milind Agrawal
  • 2,724
  • 1
  • 13
  • 20
0

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") );
A. Meshu
  • 4,053
  • 2
  • 20
  • 34