Home > Mobile >  How to copy specific values of array to another array in Javascript?
How to copy specific values of array to another array in Javascript?

Time:07-08

I have 2 arrays like this:

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}
]

I want to copy values of arr1 to arr2 where checked is true only, more than that if arr1 value is already exist in arr2 I just want it to update its qty not duplicate again. But my problem is that in some scenarios I got it duplicate and update at the same time. Below here I try with for loops.

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)
}

What went wrong here, any solution? Thanks in advance

CodePudding user response:

Here:

}else {
    if (arr1[i].checked === true) {
        newArray.push(arr1[i])
        break

You're pushing to newArray if an item is checked before iterating all the way through the second array. If the first array's item is checked, then no matter what's in the second array, you will only check what's in arr2[0] before breaking in one of the branches - which will screw up your logic.

How about grouping up the second array by ID first? It'll make more sense at a glance and will also reduce the computational complexity.

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();

If the order of arr2 must be preserved and the items may not be in ascending numerical order, use a Map instead of an object so that the order of IDs is preserved in insertion order.

CodePudding user response:

Presented below is one possible way to achieve the desired objective.

Code Snippet

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 }

Explanation

Inline comments added to the snippet above.

  • Related