After the interation, cid changed. which makes the last not pass. Why's that?

Tell us what’s happening:
Describe your issue in detail here.

  **Your code so far**
function checkCashRegister(price, cash, cid) {
let changeDue=cash-price;
let returnedObj={};
let denomination=[100, 20, 10, 5, 1, 0.25, 0.1, 0.05, 0.01];
let changeHaveGot=[["ONE HUNDRED", 0],["TWENTY", 0],["TEN", 0],["FIVE", 0],
                   ["ONE",0],["QUARTER", 0],["DIME", 0],["NICKEL", 0],["PENNY", 0]];
let cidHighToLow=cid.reverse();
let amountInDrawer=cidHighToLow.reduce((sum, item)=>sum=sum+item[1],0);
// console.log(amountInDrawer);
// if(amountInDrawer===changeDue)  {
//   returnedObj.status="CLOSED"; returnedObj.change=cid;
// }
for(let i=0; i<cidHighToLow.length; i++){
    while(denomination[i]<=changeDue.toFixed(2) && cidHighToLow[i][1]>0){
      changeHaveGot[i][1]=changeHaveGot[i][1]+denomination[i];
      cidHighToLow[i][1]=cidHighToLow[i][1]-denomination[i];
      changeDue=changeDue-denomination[i];
    }
  }
  
  // console.log(Number(changeDue.toFixed(2)));
  // console.log(Number(changeDue.toFixed(2))===0);
  let amountRestInDrawer=cidHighToLow.reduce((sum, item)=>sum=sum+item[1],0);
  // console.log(Number(amountRestInDrawer.toFixed(2)));
  let amountHaveGot=changeHaveGot.reduce((sum, item)=>sum=sum+item[1],0);
  // console.log(Number(amountHaveGot.toFixed(2)));
  let changeReal=changeHaveGot.filter(item=>item[1]>0).map(item=>{
    item[0]=item[0]; item[1]=item[1]; return item;
  });
  let cidFixed=cid.map(item=>{
    item[0]=item[0]; item[1]=Number(item[1].toFixed(2)); return item;
  }).reverse();
  console.log(cidFixed);
  // console.log(changeReal);
  if(Number(changeDue.toFixed(2))>0){
    returnedObj.status="INSUFFICIENT_FUNDS"; returnedObj.change=[];
  }else if(Number(amountRestInDrawer.toFixed(2))===0&&Number(changeDue.toFixed(2))===0){
    returnedObj.status="CLOSED"; returnedObj.change=cidFixed;
  } else {
    returnedObj.status="OPEN"; returnedObj.change=changeReal;
  }
console.log(returnedObj);
return returnedObj;
}

// checkCashRegister(19.5, 20, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]);
// checkCashRegister(3.26, 100, [["PENNY", 1.01], ["NICKEL", 2.05], ["DIME", 3.1], ["QUARTER", 4.25], ["ONE", 90], ["FIVE", 55], ["TEN", 20], ["TWENTY", 60], ["ONE HUNDRED", 100]]);
checkCashRegister(19.5, 20, [["PENNY", 0.5], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]]);
  **Your browser information:**

User Agent is: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36

Challenge: Cash Register

Link to the challenge:

1 Like

Hi

This line of code doesn’t do what you think it does:

let cidHighToLow=cid.reverse();

The reverse method updates in place, so this reverses the cid array and returns a reference to the reversed cid array.
So any modifications to cidHighToLow will also affect the cid array.

This FCC article on how to clone an array might be useful - but bear in mind that the cid array is multi-dimensional (nested) so to safely clone the cid array you’ll need a “deep copy”.

Thank you. But I think that’s not the point. The result is the same even if I use slice method to get a new cid before the line you mentioned.

If you change the inner arrays you are changing those of the original cid, you would need a deep copy, or change logic flow altogether

You are for example changing cid here

let cidFixed=cid.map(item=>{
	    item[0]=item[0]; item[1]=Number(item[1].toFixed(2)); return item;
	  }).reverse();

Do not do sssignment inside map. Return an array without using assignments

Just to expand on @ilenia 's reply, here’s an example using slice() to copy a multi-dimensional array:

const originalArray = [["a", "b"], ["c", "d"], ["e", "f"]];
const clonedArray = originalArray.slice();     // this is a shallow copy
clonedArray.reverse();      //   this is OK

console.log("original array", originalArray);
console.log("cloned array", clonedArray);

/*    console log output
original array [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e', 'f' ] ]
cloned array [ [ 'e', 'f' ], [ 'c', 'd' ], [ 'a', 'b' ] ]
*/

clonedArray[2][1] = "this has changed"; // this is not ok

console.log("original array", originalArray);
console.log("cloned array", clonedArray);

/*    console log output
original array [ [ 'a', 'this has changed' ], [ 'c', 'd' ], [ 'e', 'f' ] ]
cloned array [ [ 'e', 'f' ], [ 'c', 'd' ], [ 'a', 'this has changed' ] ]
*/

As you can see, changing the content of an element of the cloned array does, in fact, change the content of the original array.

Inside your for loop, your code has:
cidHighToLow[i][1]=cidHighToLow[i][1]-denomination[i];

which modifies the cid array.

This is explaination is very clear. Thank you so much. So what is the best method to get a cloned array without affceting the original at all in such scenarios?

you make a deep copy, there are a few ways to do that.

Or use non-mutating methods.

Map is one, if you don’t do this,

Exampel of thing to do to not change item (which is a reference to one of the arrays inside cid:

item => [item[0], Number(item[1].toFixed(2))]

Thank you so much. Thank you for helping me understand this completely.

The article in my earlier post has an example of creating a deep copy using JSON.parse and JSON.stringify (it’s near the end of the article).

But you could also consider trying to find a solution that avoids the need to update the array during your for loop.

For example, extracting a primitive value (string, number etc. ) from a nested array and storing it elsewhere allows you to update that value without affecting the array.

const originalArray = [["a", "b"], ["c", "d"], ["e", "f"]];
const clonedArray = originalArray.slice();

console.log("original array", originalArray);
console.log("cloned array", clonedArray);

/*  console log output
original array [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e', 'f' ] ]
cloned array [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e', 'f' ] ]
*/

let someVariableName = clonedArray[2][1];   // value extracted from array
console.log("someVariableName:", someVariableName);
/*  console log output
someVariableName: f
*/

someVariableName = "I can safely change this value!";

console.log("someVariableName:", someVariableName);
console.log("original array", originalArray);
console.log("cloned array", clonedArray);

/*  console log output
someVariableName: I can safely change this value!
original array [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e', 'f' ] ]
cloned array [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e', 'f' ] ]
*/

This is very clear. Appreciate.