Búsqueda de sitios web

javascript - ¿Cómo puedo encontrar y actualizar valores en un arreglo de objetos?


Tengo un array de objetos. Quiero buscar por algún campo y luego cambiarlo:

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

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

Quiero que cambie el objeto original. ¿Cómo? (No me importa si también estará en Lodash.)

Respuesta #1

Puedes usar findIndex para encontrar el índice en el arreglo del objeto y reemplazarlo según sea necesario:

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

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

Esto supone IDs únicos. Si tus IDs están duplicados (como en tu ejemplo), probablemente sea mejor que uses forEach:

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

Respuesta #2

Mi mejor enfoque es:

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

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

Referencia para findIndex

Y en caso de que no quieras reemplazar con un nuevo objeto, sino copiar los campos de item, puedes usar Object.assign:

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

como una alternativa con .map():

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

Enfoque funcional:

No modifiques el array, usa uno nuevo, para que no generes efectos secundarios

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

Nota

Usadas correctamente, las referencias a objetos no se pierden, por lo que incluso podrías usar la referencia al objeto original, en lugar de crear nuevas.

const myArr = [{ id: 1 }, { id: 2 }, { id: 9 }];
const [a, b, c] = myArr;
// modify original reference will change object in the array
a.color = 'green';
console.log(myArr[0].color); // outputs 'green'

Este problema generalmente ocurre al consumir listas de la base de datos y luego mapear la lista para generar contenido HTML que modificará los elementos de la lista, y luego necesitamos actualizar la lista y enviarla de nuevo a la base de datos como una lista.

La buena noticia es que se mantienen las referencias, así que podrías organizar tu código para aprovecharlo, y pensar en una list como un Objeto con identidades gratis, que son enteros desde 0 hasta length -1. Así que cada vez que accedas a cualquier propiedad de tu Objeto, hazlo como list[i], y no pierdes la referencia, y el objeto original se modifica. Ten en cuenta que esto es útil cuando tu fuente de verdad es solo una (el Objeto creado), y tu aplicación siempre está consumiendo de manera consistente el mismo Objeto (no recuperando varias veces de la base de datos y asignándolo a list a lo largo de la vida del componente).

La mala noticia es que la arquitectura está mal, y deberías recibir un objeto por ids (diccionario) si esto es lo que necesitas, algo así

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

De esta manera, no buscas en arrays, lo cual consume recursos. Simplemente "accedes por clave en el objeto", lo cual es instantáneo y eficiente.

Respuesta #3

Una línea usando el operador de propagación.

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

Respuesta #4

Otro enfoque es usar splice.

El método splice() cambia el contenido de un arreglo eliminando o reemplazando elementos existentes y/o agregando nuevos elementos en su lugar.

N.B : En caso de que estés trabajando con frameworks reactivos, actualizará la "vista", tu arreglo "sabiendo" que lo has actualizado.

Respuesta :

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

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

Y en caso de que solo quieras cambiar el valor de un elemento, puedes usar la función 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

Respuesta #5

Dado un objeto modificado y un arreglo:

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

Actualiza el array con el nuevo objeto iterando sobre el array:

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

Artículos relacionados