Find and replace object in array (based on id)

試著忘記壹切 提交于 2020-06-25 18:14:15

问题


Got a bit of a puzzle here...I want to loop through allItems and return allItems but replace with any newItems that matches its id. How can I look for a match on id and then replace it with the correct object into the array?

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'
  }
]

What I tried so far:

for(let i = 0; i < allItems.length; i++) {
  if(newItems.indexOf(allItems[i].id) > -1){
    allItems[i] = newItems
  }
}

How can I get the position of the object in newItems and then replace it into allItems?


回答1:


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.




回答2:


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



回答3:


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



回答4:


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



回答5:


You could get a reference to the object you are looking for by id but that would not be enough because then you would need the index in order to replace it in allItem (allItem[index] = newItem), so I suggest finding that index instead first like this:

for (let item of newItems) {
    let indexNewItem = allItems.map(function (e) { return e.id }).indexOf(item.id);
    allItems[indexNewItem] = item
}

this should work



来源:https://stackoverflow.com/questions/54876239/find-and-replace-object-in-array-based-on-id

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!