Find and replace object in array (based on id)

Just using a simple Array.map and a method to check the other array.

const allItems = [
  {
    'id': 1,
    'category_id': 1,
    'text': 'old',
  },
  {
    'id': 2,
    'category_id': 1,
    'text': 'old'
  },
  {
    'id': 3,
    'category_id': 1,
    'text': 'old_same'
  }
  
]

const newItems = [
  {
    'id': 1,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  },
  {
    'id': 2,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  }
]

const findNewItem = (oldItem) => newItems.find(item => item.id === oldItem.id);

let arr = allItems.map(item => findNewItem(item)||item);

console.log(arr);

Use Array.map and Array.find():

const allItems = [
  { 'id': 1, 'category_id': 1, 'text': 'old' },
  { 'id': 2, 'category_id': 1, 'text': 'old' }
];

const newItems = [
  { 'id': 1, 'category_id': 1, 'text': 'new', 'more_info': 'abcd' },
  { 'id': 2, 'category_id': 1, 'text': 'new', 'more_info': 'abcd' }
];

const result = allItems.map(x => {
  const item = newItems.find(({ id }) => id === x.id);
  return item ? item : x;
});

console.log(result);

This can even be shortened by using a logical or to return the original item when the call to find returns undefined:

const result = allItems.map(x => newItems.find(({ id }) => id === x.id) || x);

Regarding your code, you can't use indexOf since it only compares primitive values or references in the case of arrays and objects.


Just use map like so:

const allItems = [{
    'id': 1,
    'category_id': 1,
    'text': 'old',
  },
  {
    'id': 2,
    'category_id': 1,
    'text': 'old'
  }
];
const newItems = [{
    'id': 1,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  },
  {
    'id': 2,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  }
];

const replacedItems = allItems.map(e => {
  if (newItems.some(({ id }) => id == e.id)) {
    return newItems.find(({ id }) => id == e.id);
  }
  return e;
});

console.log(replacedItems);

Depending on how large your input arrays are, you might consider adding an intermediate step to build a "map" of your newItems, where the key of this map is the id of the item.

Using a mapping such as this would allow for much faster reconciliation (and replacement) of items from the allItems array with items in the newItems array:

function replaceItemsOnId(items, replacement) {

  /* 
  Create a map where the key is the id of replacement items.
  This map will speed up the reconciling process in the 
  subsequent "map" stage
  */
  const replacementMap = replacement.reduce((map, item) => {

    map[ item.id ] = item
    return map;

  }, {})

  /*
  Map the items to a new array where items in the result array
  are either clones of the orignals, or replaced by items of 
  "replacement" array where thier id matches the item being mapped 
  */
  return items.map(item => {

    const use = replacementMap[ item.id ] || item

    return { ...use }

  })
}

const allItems = [
  {
    'id': 1,
    'category_id': 1,
    'text': 'old',
  },
  {
    'id': 2,
    'category_id': 1,
    'text': 'old'
  }
]

const newItems = [
  {
    'id': 1,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  },
  {
    'id': 2,
    'category_id': 1,
    'text': 'new',
    'more_info': 'abcd'
  }
]


console.log(replaceItemsOnId(allItems, newItems))