2

Orig Problem

I was working on an exercise that should sum up the amount of change left in a cash register, variable cid.

cid looks something like this:

var cid = [["PENNY", 0], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]];

In a case like this, when all of the values are 0, then I should report that the register is empty.

I thought something like this should work:

if (cid.reduce(function(prevVal, curVal) {
  return prevVal[1] + curVal[1];
}) === 0)

But it didn't.


Digging In

Some strange things seem to happen when working with arrays within arrays and the reduce method. For instance:

cid.reduce(function(prevVal, curVal) {
  return prevVal[1] + curVal[1];
});

NaN

Whereas, if I just let the entire array through, I do get something, albeit something strange:

cid.reduce(function(prevVal, curVal) {
  return prevVal + curVal;
});

"PENNY,0NICKEL,0DIME,0QUARTER,0ONE,0FIVE,0TEN,0TWENTY,0ONE HUNDRED,0"

It's clear to me that, when using reduce, it isn't simply delving one level deeper into the array / object, as I had suspected it would.

However, the only other thing I might have suspected is also wrong: it's not delving into all the levels, either. If this were the case, I would have expected to have seen something like this (notice there are no commas):

"PENNY0NICKEL0DIME0QUARTER0ONE0FIVE0TEN0TWENTY0ONE HUNDRED0"

Two Questions

  1. Is there any way to effectively use the reduce method with multi-dimensional arrays like this?
  2. Can anyone help me understand what is going on under the hood here?
4
  • array + array === array.toString() + array.toString() Commented Apr 20, 2016 at 23:53
  • The two answers below nailed it - just wanted to point out that you're actually returning the number of coins/notes you have, not their value. Commented Apr 21, 2016 at 0:00
  • So is that supposed to be [[["PENNY", 0], "NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]] or [["PENNY", 0], ["NICKEL", 0], ["DIME", 0], ["QUARTER", 0], ["ONE", 0], ["FIVE", 0], ["TEN", 0], ["TWENTY", 0], ["ONE HUNDRED", 0]] Commented Apr 21, 2016 at 0:02
  • @jdphenix No, it isn't. I made a typo, and have now fixed it. Sorry for any confusion. Commented Apr 21, 2016 at 0:21

3 Answers 3

4

You're slightly misunderstanding the nature of reduce; the value in prevVal is not whatever value we were called with last; it's whatever value we returned last. Since you are returning an integer, prevVal is an integer, and prevVal[1] is undefined.

I'd suggest you alter your call to reduce to provide an explicit default of 0, and rewrite your function to assume that prevVal is always going to be a number, not a value in your array.

var cid = [
  ["PENNY", 0],
  ["NICKEL", 0],
  ["DIME", 0],
  ["QUARTER", 0],
  ["ONE", 0],
  ["FIVE", 0],
  ["TEN", 0],
  ["TWENTY", 0],
  ["ONE HUNDRED", 0]
]

var val = cid.reduce(function(prevVal, curVal) {
  return prevVal + curVal[1];
}, 0);

document.write("<pre>" + JSON.stringify(val) + '</pre>');

Sign up to request clarification or add additional context in comments.

1 Comment

Yes, thanks! I did misunderstand that subtle aspect for what prevVal really represents within reduce. The way you explained it is great, and that implementation of reduce makes a lot of sense.
2

The following should work

cid.reduce( (memo, item) => memo + item[1], 0)

or

cid.reduce( function(memo, item) { return memo + item[1] }, 0)

Comments

1

No one explained to you what was happening 'under the hood' so I will take a shot at it.

So this is basically what is happening:

 cid.reduce(function(prevVal, curVal) {
    return prevVal[1] + curVal[1];
 });

 NaN

In this case you are grabbing two arrays which javascript tries to coerce and it results in NaN

Here:

cid.reduce(function(prevVal, curVal) {
   return prevVal + curVal;
});

It is reducing each element in each array but the return statement tries to reduce a string and a number. In js 0 + "string" is 0string because js coerce the number to a string and then concatenates them.

1 Comment

Thanks, but I am still confused. Near the end, you say 0 + "string" is 0string, which is exactly what I would have thought, but that is not what I saw. Instead, it somehow coerced and created a comma. That was the part which really confused me. Also, I think I am grabbing two arrays in both attempts, it's just that the first attempt I further try to reduce to a single value. @Hamms explanation still makes the most sense to me: the prevVal becomes just an integer, since it is the return, whereas the curVal is still an array that must be subset.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.