Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

JavaScript JavaScript Array Iteration Methods Array Manipulation Return a Single Value from an Array with reduce()

Akash Sharma
seal-mask
.a{fill-rule:evenodd;}techdegree
Akash Sharma
Full Stack JavaScript Techdegree Student 14,147 Points

return count + 1 vs. return count++

Why am I getting 0 for this code:

const names = ['Gary', 'Pasan', 'Gabe', 'Treasure', 'Gengis', 'Gladys', 'Tony'];
const gNames = names.reduce((count, name) => {
  if (name[0] === 'G'){
    return count++;
  }
  return count;
}, 0);
console.log(gNames);   

And 4 for this code:

const names = ['Gary', 'Pasan', 'Gabe', 'Treasure', 'Gengis', 'Gladys', 'Tony'];
const gNames = names.reduce((count, name) => {
  if (name[0] === 'G'){
    return count+1;
  }
  return count;
}, 0);
console.log(gNames);   

3 Answers

Agree. Neil, my answer didn't really cover the issue - that's me skim-reading as usual!!

I think this might be to do with the use of two return statements. If you code this with one return, as I normally would (I don't use node or js, though!), and just return the value of count at the end, then this behaves how I would expect:

const gNameCount = names.reduce((count, name) => {
  if (name[0] === 'G'){
    count + 1;
  }
  return count;
}, 0);

This returns zero as the value held in count is never altered, so we get the specified initial value of zero, whereas:

const gNameCount = names.reduce((count, name) => {
  if (name[0] === 'G'){
    count++;
  }
  return count;
}, 0);

... returns 4 as we are modifying the value in count with the increment operator, then returning that value at the end.

In this next example, maybe count is an accumulator picking up the returned value on each iteration, perhaps? Thus it would add one (initial value + 1) on each iteration of a letter starting with 'G', storing that in count as an accumulator? A letter not starting with 'G' would 'accumulate' a zero (the initial value) and thus not affect adversely what we would expect to see.

const gNameCount = names.reduce((count, name) => {
  if (name[0] === 'G'){
    return count + 1;
  }
  return count;
}, 0);

But, I don't understand why using return count++ produces, specifically, zero. I would expect it to mess with the loop, perhaps, and maybe generate unexpected results - but not zero. It is as if the reduce function is just not working?!

This doesn't work in my mind:

const gNameCount = names.reduce((count, name) => {
  if (name[0] === 'G'){
    return count++;
  }
  return count;
}, 0);

I can understand this creating odd results, as if we're accumulating G's but adding one to count, the first 'G' would correctly accumulate a 1, but the second would accumulate a 2, the third a 3 etc. Thus we'd get a large number output at the end. But we don't see this - we get, consistently, a zero.

I did some logging - this works very nearly as we would expect:

const gNameCount = names.reduce((count, name) => {
  if (name[0] === 'G'){
    console.log(count++)
    return count;
  }
  return count;
}, 0);

console.log(gNameCount);

I'm logging the value of count at each iteration. I get this output:

treehouse:~/workspace$ node iteration.js                                                         
0                                                                                                
1                                                                                                
2                                                                                                
3                                                                                                
4                                                                                                
5                                                                                                

But that's not right, is it? (although it has fixed the code - which now outputs the right number - I've added an extra 'G' name in the array, hence a 5). Why aren't there two 5s at the end, one mid-code and then the final output from the console.log underneath the method? And how come this works all of a sudden? That got me thinking about timing of the increment. I think that return count++; returns count then increments it. But that change is lost so count remains as zero, the change isn't included in the returned value, as it is returned first, so that change is dropped. I tested this theory with this:

const gNameCount = names.reduce((count, name) => {
  if (name[0] === 'G'){
    console.log(count)
    return ++count;
  }
  return count;
}, 0);

This increments count first by using the increment operator before the variable, and so the change is persisted into the next iteration. This works and solves your problems and answers your question! The reason your were getting zero was because the increment operator hadn't operated by the time the value was returned so the increment never happened. You need to increment with a preceding ++ operator to persist that change - i.e. to return an updated value for count.

The act of returning the value of count must update its value within the reduce method. The use of either + 1 or ++ is irrelevant - it just wants to know what value to store. The count++ method doesn't work as the increment is too late so using either a preceding ++ or just sending back count + 1 is sufficient to update the value held within the iteration.

So, apologies for a few things - 1. the initial nonsense answer I gave back in November, 2. the thought-process post presented here; I literally typed this as I tested!

I hope this now answers the question and I am redeemed. :smile:

Your thoughts are welcomed!

Steve.

Neil McPartlin
Neil McPartlin
14,660 Points

Hi Steve. Not only have you redeemed yourself, you have excelled yourself too :)

I follow and agree with pretty much everything you have written. I was unaware of ++count let alone the big difference it makes as to which side of the count, placing your ++ makes. I think I understand your logging issue too.

I just took your code and added some additional labels (plus a 5th G name).

const names = ['Gary', 'Pasan', 'Gabe', 'Treasure', 'Gengis', 'Gladys', 'Tony', 'Gill'];
const gNameCount = names.reduce((count, name) => {
    if (name[0] === 'G'){
      console.log('count++: ', count++)
    //   console.log('++count: ', ++count)
      console.log('count: ', count)
      return count;
    }
    return count;
  }, 0);

  console.log('gNameCount: ', gNameCount);

//Result

// count++:  0
// count:  1
// count++:  1
// count:  2
// count++:  2
// count:  3
// count++:  3
// count:  4
// count++:  4
// count:  5
// gNameCount:  5

So with your code, even with the first G match, count++ still reports 0 presumably until 'return count' takes place. This is why your initial log only shows a single 5. If you were to comment out the count++ log, and uncomment the ++count log, this would look more like you had expected with ++count reporting the same as count..

Thanks so much for your time on this.

Hi Neil,

Thanks for the feedback; it annoyed me that I couldn't figure out what was going on, so I invested a little time on this, and dug out a distant memory regarding the placement of the ++ operator!

Yes, the log occurs before the increment on each iteration now, so the log will be 'behind' the variable value as it exits each iteration.

Glad to have helped sort this despite not being a js developer! It just goes to show that the basic principles are common across most languages!

Steve.

Great answer, very helpful. I still have a question about the return keyword. I understand that return count++ returns count before it is updated. But why does return count + 1 work? Shouldn't this also return count before it is updated?

Hi there,

count + 1 doesn't affect the value of count - you would need to reassign back into count, like: count = count + 1. Otherwise, you are just returning the value one greater than stored in count. The increment operator does what it says; increments! So it affects the value stored within count.

Steve,.

Neil McPartlin
Neil McPartlin
14,660 Points

Hi Steve Hunter & Akash Sharma,

I seem to be having a brain freeze here because although I understand your answer Steve, it doesn't actually explain what Akash and I are witnessing. Just to recap...

return count++; // This fails.
//My expectation like for Akash is that it would increment 'count' by one.

return count = count + 1; // This works and I'd guess we all agree why.

return count + 1; // This works but why?
//As Steve says, it should not succeed in incrementing 'count' by 1,
//but it does. In fact, this is the solution shown by the teacher in the video.

It feels like different rules apply when incrementing 'count' within a 'reduce' function.

Justin Hicks
Justin Hicks
14,290 Points

I realize this is not the most recent conversation, but I definitely hope you guys know how much I appreciate the in-depth answer. It has opened my eyes to just how specific code can be. While I did not do it exactly as the teacher or you guys did, the same issue persisted for my code. This resulted in 0;

const beginG = names.reduce((count, name) => {
  if(name.startsWith('G') === true) {
   count + 1;
  }
  return count;
}, 0);
console.log(beginG); 

While this had the correct result of 4.

const beginG = names.reduce((count, name) => {
  if(name.startsWith('G') === true) {
   return count + 1;
  }
  return count;
}, 0);
console.log(beginG);

Again thank you guys for the indepth conversation. It has helped me more then you know!

Glad to have helped a little, Justin! :+1: :smile: