Tengo 2 matrices como esta:
const arr1 = [ {id: 1, qty: 2, checked: true}, {id: 2, qty: 2, checked: true}, {id: 3, qty: 2, checked: false} ] const arr2 = [ {id: 1, qty: 2}, {id: 2, qty: 2} ] Quiero copiar valores de arr1 a arr2 donde checked es true solamente, más que eso si el valor arr1 ya existe en arr2 solo quiero que actualice su qty y no se duplicate nuevamente. Pero mi problema es que en algunos escenarios lo dupliqué y lo actualicé al mismo tiempo. A continuación, pruebo con bucles for.
const handleAdd = () => { let newArray = [...arr2] for (let i = 0; i < arr1.length; i++) { for (let j = 0; j < arr2.length; j++) { if(arr2[j].id === arr1[i].id && arr1[i].checked === true){ newArray[j].qty = newArray[j].qty + arr1[i].qty break }else{ if(arr1[i].checked === true){ newArray.push(arr1[i]) break } } } } console.log(newArray) }¿Qué salió mal aquí, alguna solución? Gracias por adelantado
Aquí:
}else { if (arr1[i].checked === true) { newArray.push(arr1[i]) break Está presionando a newArray si un elemento se verifica antes de iterar completamente a través de la segunda matriz. Si el elemento de la primera matriz está marcado, no importa lo que haya en la segunda matriz, solo comprobará lo que hay en arr2[0] antes de interrumpir una de las ramas, lo que estropeará su lógica.
¿Qué tal agrupar primero la segunda matriz por ID? Tendrá más sentido de un vistazo y también reducirá la complejidad computacional.
const arr1 = [ {id: 1, qty: 2, checked: true}, {id: 2, qty: 2, checked: true}, {id: 3, qty: 2, checked: false} ] const arr2 = [ {id: 1, qty: 2}, {id: 2, qty: 2} ] const handleAdd = () => { const qtyById = Object.fromEntries( arr2.map(({ id, qty }) => [id, qty]) ); for (const item of arr1) { if (item.checked) { qtyById[item.id] = (qtyById[item.id] || 0) + item.qty; } } const newArray = Object.entries(qtyById).map(([id, qty]) => ({ id, qty })); console.log(newArray) } handleAdd(); Si se debe conservar el orden de arr2 y es posible que los elementos no estén en orden numérico ascendente, utilice un mapa en lugar de un objeto para que el orden de los ID se conserve en el orden de inserción.
A continuación se presenta una posible forma de lograr el objetivo deseado.
Fragmento de código
const myAdd = (needle, hayStack) => ( hayStack.map( ({id, qty}) => ({ id, qty, ...( needle.some(n => n.checked && n.id === id) ? ( { qty } = needle.find(n => n.checked && n.id === id), { qty } ) : {} ) }) ).concat( needle .filter( ({ id, checked }) => checked && !hayStack.some(h => h.id === id) ).map(({ id, qty }) => ({ id, qty })) ) ); /* explanation // method to add or update arr2 const myAdd = (needle, hayStack) => ( // first iterate over "arr2" (called hayStack here) // and update each item by matching "id" when "arr1" (called needle here) // has "checked" true hayStack.map( // de-structure "arr2" to directly access "id" and "qty" ({id, qty}) => ({ id, qty, // by default populate both "id" and "qty" ...( // if "arr1" has a matching "id" and "checked" is true // then, ".find()" the particular elt and // update the "qty" needle.some(n => n.checked && n.id === id) ? ( // extract only the "qty" from result ".find()" { qty } = needle.find(n => n.checked && n.id === id), { qty } // return an object with one prop "qty" ) : {} // if "arr1" has no matching "id", no change to "arr2" elt ) }) ).concat( // concat items in "arr1" which are not already present in "arr2" // and have "checked" as "true" needle .filter( // first filter only "new" items ({ id, checked }) => checked && !hayStack.some(h => h.id === id) ).map( // destructure to extract only "id" and "qty" props ({ id, qty }) => ({ id, qty }) ) ) ); */ const arr1 = [ {id: 1, qty: 3, checked: true}, {id: 2, qty: 2, checked: true}, {id: 3, qty: 2, checked: false}, {id: 4, qty: 4, checked: true} ]; const arr2 = [ {id: 1, qty: 2}, {id: 2, qty: 2} ]; console.log( 'add/update elements from arr1:\n', JSON.stringify(arr1), '\n\ninto arr2: ', JSON.stringify(arr2), '\n\n', myAdd(arr1, arr2) ); .as-console-wrapper { max-height: 100% !important; top: 0 }Explicación
Se agregaron comentarios en línea al fragmento anterior.