Поиск элемента в массиве на основе другого массива и изменение свойства

У меня есть два массива таких объектов:

const officers: any[] = [
  { id: 20, name: 'Captain Piett' },
  { id: 24, name: 'General Veers' },
  { id: 56, name: 'Admiral Ozzel' },
  { id: 88, name: 'Commander Jerjerrod' }
];

const searchAndChangeFor: any[] = [
  { id: 56, name: 'New Name', additionalData: 1 },
];

Я хочу найти элементы из searchAndChangeFor в officers и изменить содержимое. Обычно если у меня есть один элемент, я делаю это:

officers.map((item) => {
    // I want to modify id: 56 and update officers here.
    item.id === 56 ? { ...item, name: 'Change name for 56' } : item
}); 

Но мне нужно искать по массиву, а не по одному элементу, поэтому я пробовал это, но не преуспел:

officers.map((item) => {
   searchAndChangeFor.find((item2) => {
       item.id === item2.id? { ...item, name: 'Change name for 56' } : item
   }); 
}); 

Ожидаемый результат:

  { id: 20, name: 'Captain Piett' },
  { id: 24, name: 'General Veers' },
  { id: 56, name: 'New Name', additionalData: 1 },
  { id: 88, name: 'Commander Jerjerrod' }

Он сходит с ума с массивом. Как я могу найти элементы в officers на основе searchAndChangeFor и изменить его имя? Я также хочу сохранить все остальные существующие предметы в офицерах.

Либо добавьте return внутри map и find, либо удалите {} для неявного возврата.

adiga 28.05.2019 10:09

Все ли предметы из searchAndChangeFor существуют в officers?

adiga 28.05.2019 10:10

да. Нет новых значений в searchAndChangeFor

Dennis 28.05.2019 10:11
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
60
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Вы можете найти товар и поменять на найденное имя или вернуть товар без сдачи.

const
    officers = [{ id: 20, name: 'Captain Piett' }, { id: 24, name: 'General Veers' }, { id: 56, name: 'Admiral Ozzel' }, { id: 88, name: 'Commander Jerjerrod' }],
    searchAndChangeFor = [{ id: 56, name: 'New Name', additionalData: 1 }],
    result = officers.map((item) => {
        let temp = searchAndChangeFor.find((item2) => item.id === item2.id); 
        return temp ? { ...item, name: temp.name } : item;
    });

console.info(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Проблема с вашим кодом заключается в том, что .map ожидает, что вы вернете значение, которое будет сохранено в результирующем массиве, тогда как вы ничего не возвращаете.

Вы можете сохранить массив всех идентификаторов searchAndChangeFor. Это будет вычислено только один раз, поэтому оно будет эффективным, и его будет легче сравнивать с officer.id в .map.

const officers = [
  { id: 20, name: 'Captain Piett' },
  { id: 24, name: 'General Veers' },
  { id: 56, name: 'Admiral Ozzel' },
  { id: 88, name: 'Commander Jerjerrod' }
];

const searchAndChangeFor = [
  { id: 56, name: 'Admiral Ozzel' },
];

const allIDsToChange = searchAndChangeFor.map(el => el.id);
const newOfficers = officers.map((item) => allIDsToChange.includes(item.id) ? { ...item,
  name: 'Change name for 56'
} : item);

console.info(newOfficers);

find ожидает логический ответ, когда он получает true, он возвращает элемент, для которого было возвращено true, вы пытаетесь изменить элемент непосредственно в теле обратного вызова find. Это не то, что вам нужно делать, вы хотите просто изменить значение, в котором идентификатор существует в вашем массиве searchAndChangeFor for.

const ids = searchAndChangeFor.map((rel) => rel.id);
const changed = officers.map((item) => ids.includes(item.id) ?
    {{ Item mutation logic here }} :
    item);

вы можете найти элемент и, если он найден, изменить имя и вернуть измененный элемент или просто вернуть элемент (без изменений)

officers.map((item) => {
   searchAndChangeFor.find((item2) => {
       if (item.id === item2.id) {
          return { ...item, name: 'Change name for 56' } 
       }
   }) || item; 
});
Ответ принят как подходящий

Вы могли бы map массив офицеров. Получите объект с тем же id в searchAndChangeFor, используя find. Объедините их, используя синтаксис распространения

Если вы просто хотите объединиться, вы можете просто сделать

return { ...item, ...searchAndChangeFor.find(o => o.id === item.id) } 

Но если вы хотите добавить новые свойства при обнаружении совпадения, вы можете условно вернуться, как показано ниже:

const officers=[{id:20,name:'Captain Piett'},{id:24,name:'General Veers'},{id:56,name:'Admiral Ozzel'},{id:88,name:'Commander Jerjerrod'}],
    searchAndChangeFor = [{id:56,name:'New Name',additionalData:1},];
    
const output = officers.map(item => {
  const found = searchAndChangeFor.find(o => o.id === item.id);
  if (found)
    return { ...item, ...found, newProperty: 'value' }
  else
    return item;
})

console.info(output)

Другой вариант - клонировать массив officers, чтобы избежать мутаций, и вместо этого перебирать searchAndChangeFor (поскольку это меньший массив)

const officers=[{id:20,name:'Captain Piett'},{id:24,name:'General Veers'},{id:56,name:'Admiral Ozzel'},{id:88,name:'Commander Jerjerrod'}],
    searchAndChangeFor = [{id:56,name:'New Name',additionalData:1},],
    output = [...officers];

searchAndChangeFor.forEach(s => {
  const index = officers.findIndex(o => o.id === s.id);
  output[index] = Object.assign({}, output[index], s)
})

console.info(output)

Я хотел бы иметь возможность изменять совпадающий элемент за пределами searchAndChangeFor. Например, я добавил additionalData. Я хочу добавить больше свойств, когда найду соответствующий элемент. Решение Нины находит его и модифицирует на лету. Кроме того, массив огромен в реальном мире. Я не хочу его клонировать. (Но я думаю, что второй подход лучше, потому что поиск невелик)

Dennis 28.05.2019 10:27

На выходе есть additionalData. Если вы хотите добавить больше свойств, вы можете добавить их после разворота поиска. { ...item, ...searchAndChangeFor.find(o => o.id === item.id), anotherProperty: "value" }

adiga 28.05.2019 10:29

Но что будет добавляться ко всем элементам или только к совпавшему элементу?

Dennis 28.05.2019 10:29

@Pratha, тогда вам придется использовать тернарный оператор для find. Кроме того, вы согласны с мутацией массива officers с использованием forEach? Или вам нужен новый массив без изменения officers?

adiga 28.05.2019 10:32

@Pratha обновил первый фрагмент, чтобы добавить новые свойства, когда совпадение найдено.

adiga 28.05.2019 10:34

Предполагая, что вы хотите сохранить все свойства объектов officers и searchAndChangeFor:

const officers = [
    { id: 20, name: 'Captain Piett' },
    { id: 24, name: 'General Veers' },
    { id: 56, name: 'Admiral Ozzel', admiralSince: 2008 },
    { id: 88, name: 'Commander Jerjerrod' }
];

const searchAndChangeFor = [
    { id: 56, name: 'New Name', additionalData: 1 },
];

const newOfficers = officers.map(officer => {
    const changedOfficer = searchAndChangeFor.find(changedOfficer => changedOfficer.id === officer.id)
    return changedOfficer ? { ...officer, ...changedOfficer } : officer;
});

console.info(newOfficers);

Другие вопросы по теме