У меня есть массив объектов. Хочу найти по какому-то полю, а потом поменять:

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

var foundItem = items.find(x => x.id == item.id);
foundItem = item;

Я хочу изменить исходный объект. Как? (Меня не волнует, будет ли это тоже в lodash)

Ответы (9)

Вы можете использовать findIndex, чтобы найти индекс в массиве объекта и при необходимости заменить его:

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

var foundIndex = items.findIndex(x => x.id == item.id);
items[foundIndex] = item;

Это предполагает уникальные идентификаторы. Если ваши идентификаторы дублируются (как в вашем примере), вероятно, лучше использовать forEach:

items.forEach((element, index) => {
    if(element.id === item.id) {
        items[index] = item;
    }
});

Однострочное использование оператора спреда.

 const updatedData = originalData.map(x => (x.id === id ? { ...x, updatedField: 1 } : x));

Можно использовать Фильтр.

const list = [{id:0}, {id:1}, {id:2}];
let listCopy = [...list];
let filteredDataSource = listCopy.filter((item) => {
       if (item.id === 1) {
           item.id = 12345;
        }

        return item;
    });
console.log(filteredDataSource);

Массив [Объект {id: 0}, Объект {id: 12345}, Объект {id: 2}]

Вы тоже можете это сделать

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

var foundItem = items.filter((x) => x.id ==  item.id).pop();
foundItem = item;

ИЛИ

items.filter((x) => x.id ==  item.id).pop()=item;

 

Учитывая измененный объект и массив:

const item = {...}
let items = [{id:2}, {id:3}, {id:4}];

Обновите массив новым объектом, перебирая массив:

items = items.map(x => (x.id === item.id) ? item : x)

Несмотря на то, что большинство существующих ответов прекрасны, я хотел бы включить ответ с использованием традиционного цикла for, который также следует здесь учитывать. OP запрашивает ответ, совместимый с ES5 / ES6, и применяется традиционный цикл for:)

Проблема с использованием функций массива в этом сценарии заключается в том, что они не изменяют объекты, но в этом случае изменение является обязательным. Прирост производительности от использования традиционного цикла for - это просто (огромный) бонус.

const findThis = 2;
const items = [{id:1, ...}, {id:2, ...}, {id:3, ...}];

for (let i = 0, l = items.length; i < l; ++i) {
  if (items[i].id === findThis) {
    items[i].iAmChanged = true;
    break;
  }
}

Хотя я большой поклонник функций массива, не позволяйте им быть единственным инструментом в вашем наборе инструментов. Если целью является изменение массива, они не подходят.

Другой подход - использовать splice.

Метод splice () изменяет содержимое массива, удаляя или заменяя существующие элементы и / или добавляя новые элементы на месте.

Примечание: Если вы работаете с реактивными фреймворками, он обновит «представление», ваш массив будет «знать», что вы его обновили.

Ответ:

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

let foundIndex = items.findIndex(element => element.id === item.id)
items.splice(foundIndex, 1, item)

А если вы хотите изменить только значение элемента, вы можете использовать функцию find:

// Retrieve item and assign ref to updatedItem
let updatedItem = items.find((element) => { return element.id === item.id })

// Modify object property
updatedItem.aProp = ds.aProp

у меня работало

let returnPayments = [ ...this.payments ];

returnPayments[this.payments.findIndex(x => x.id == this.payment.id)] = this.payment;

Мой лучший подход:

var item = {...}
var items = [{id:2}, {id:2}, {id:2}];

items[items.findIndex(el => el.id === item.id)] = item;

Ссылка для findIndex

И в случае, если вы не хотите заменять новый объект, а вместо этого скопировать поля item, вы можете использовать Object.assign:

Object.assign (items [items.findIndex (el => el.id === item.id)], item)

в качестве альтернативы .map ():

Object.assign (items, items.map (el => el.id === item.id? Item: el))

Функциональный подход:

Не изменяйте массив, используйте новый, чтобы не создавать побочных эффектов

const updatedItems = items.map(el => el.id === item.id ? item : el)

Примечание

При правильном использовании ссылки на объекты не теряются, поэтому вы даже можете использовать исходную ссылку на объект вместо создания новых.

const myArr = [{id: 1}, {id: 2}, {id: 9}];
const [a, b, c] = myArr;
// изменение исходной ссылки изменит объект в массиве
a.color = 'зеленый';
console.log (myArr [0]. цвет); // выводит 'зеленый'

Эта проблема обычно возникает при использовании списков из базы данных и последующем сопоставлении списка для создания HTML-содержимого, которое изменяет элементы списка, а затем нам нужно обновить список и отправить его обратно в базу данных в виде списка.

Хорошая новость в том, что ссылки сохраняются, поэтому вы можете организовать свой код, чтобы получить преимущество, и подумайте о списке как об объекте с идентификаторами бесплатно, которые являются целыми числами от 0 до длина -1. Поэтому каждый раз, когда вы обращаетесь к какому-либо свойству вашего объекта, делайте это как list [i], и вы не теряете ссылку, а исходный объект изменяется. Имейте в виду, что это полезно, когда ваш источник истины только один (созданный объект), и ваше приложение всегда постоянно использует один и тот же объект (не извлекает несколько раз из базы данных и не назначает его списку вместе с ним). срок службы компонента).

Плохая новость в том, что архитектура неправильная, и вы должны получить объект по идентификатору (словарю), если это то, что вам нужно, что-то вроде

{
  1232: {id: 1232, ...},
  asdf234asf: {id: 'asdf234asf', ...},
  ...
}

Таким образом, вы не будете искать в массивах, что потребляет много ресурсов. Вы «просто получаете доступ к объекту с помощью ключа», что мгновенно и эффективно.

2022 WebDevInsider