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?

5
  • 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 :) Commented Sep 19, 2019 at 19:39
  • Where did name and slugName come from in your expected results? Commented Sep 19, 2019 at 19:43
  • @Maria it was old irrelevant data from a prev version. I edited my question to reflect more accurately. Commented Sep 19, 2019 at 19:45
  • 1
    Are newItem and oldItem actually in the data? Commented Sep 19, 2019 at 19:45
  • Please refer to this stackoverflow.com/questions/19480008/… Commented Sep 19, 2019 at 19:48

5 Answers 5

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);

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

Comments

0

You can use lodash for this.

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

Comments

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);

Comments

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);

Comments

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") );

2 Comments

this is great. but test is missing from current[0] in the merged results
Well @Charlie's solutions much more modern anyways (:

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.