У меня есть два массива таких объектов:
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
и изменить его имя? Я также хочу сохранить все остальные существующие предметы в офицерах.
Все ли предметы из searchAndChangeFor
существуют в 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 }],
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
. Я хочу добавить больше свойств, когда найду соответствующий элемент. Решение Нины находит его и модифицирует на лету. Кроме того, массив огромен в реальном мире. Я не хочу его клонировать. (Но я думаю, что второй подход лучше, потому что поиск невелик)
На выходе есть additionalData
. Если вы хотите добавить больше свойств, вы можете добавить их после разворота поиска. { ...item, ...searchAndChangeFor.find(o => o.id === item.id), anotherProperty: "value" }
Но что будет добавляться ко всем элементам или только к совпавшему элементу?
@Pratha, тогда вам придется использовать тернарный оператор для find
. Кроме того, вы согласны с мутацией массива officers
с использованием forEach
? Или вам нужен новый массив без изменения officers
?
@Pratha обновил первый фрагмент, чтобы добавить новые свойства, когда совпадение найдено.
Предполагая, что вы хотите сохранить все свойства объектов 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);
Либо добавьте
return
внутриmap
иfind
, либо удалите{}
для неявного возврата.