Найти и заменить объект в массиве (на основе идентификатора) - PullRequest
0 голосов
/ 26 февраля 2019

Здесь есть небольшая загадка ... Я хочу просмотреть allItems и вернуть allItems, но заменить на любой newItems, который соответствует его идентификатору.Как я могу найти совпадение на id и затем заменить его правильным объектом в массиве?

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

Что я пробовал до сих пор:

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

Как я могуполучить положение объекта в newItems и затем заменить его на allItems?

Ответы [ 5 ]

0 голосов
/ 26 февраля 2019

Вы можете получить ссылку на объект, который вы ищете, по id , но этого будет недостаточно, потому что тогда вам потребуется индекс, чтобы заменить его в allItem (allItem[index] = newItem), поэтомуВместо этого я предлагаю сначала найти этот индекс следующим образом:

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

это должно работать

0 голосов
/ 26 февраля 2019

В зависимости от размера ваших входных массивов, вы можете подумать о добавлении промежуточного шага для построения «карты» вашей newItems, где ключом этой карты является id элемента.

Использование такого сопоставления позволило бы намного быстрее согласовать (и заменить) элементы из массива allItems с элементами в массиве newItems:

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))
0 голосов
/ 26 февраля 2019

Просто используйте map вот так:

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);
0 голосов
/ 26 февраля 2019

Просто используя простой Array.map и метод для проверки другого массива.

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);
0 голосов
/ 26 февраля 2019

Использование Array.map и 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);

Это даже можно сократить с помощью логического или возврата исходного элемента, когда вызов find возвращает undefined:

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

Что касается вашего кода, вы не можете использовать indexOf, поскольку он сравнивает только примитивные значения или ссылки в случае массивов и объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...