0

Let's say I have a problem like this there I have an array of objects and I try to use Array.reduce() to count all the numbers of the different types into a new object:

var desks = [
  { type: 'sitting' },
  { type: 'standing' },
  { type: 'sitting' },
  { type: 'sitting' },
  { type: 'standing' }
];

var deskTypes = desks.reduce(function(prev, curr) {
  if(curr.type === "sitting") {
    return {sitting: ++prev.sitting, standing: prev.standing};
  }

  if(curr.type === "standing") {
      return {sitting: prev.sitting, standing: ++prev.standing};
  }
}, { sitting: 0, standing: 0 });

The above example works and everything increments perfectly. Yet, when I switch the ++ to the right side (where I usually place it to increment a value), the function returns NaN.

var deskTypes = desks.reduce(function(prev, curr) {
  if(curr.type === "sitting") {
    return {sitting: prev.sitting++, standing: prev.standing};
  }

  if(curr.type === "standing") {
      return {sitting: prev.sitting, standing: prev.standing++};
  }
}, { sitting: 0, standing: 0 });

Honestly, I have no idea what's going on here. Can anyone explain?

Mabeh Al-Zuq Yadeek
  • 46
  • 4
  • 16
  • 28
  • it should return sitting: 0, standing: 0 when having post increment operator. I've checked in jsfiddle and it's sitting: 0, standing: 0 rather than NaN – Akash KC Mar 04 '17 at 04:18
  • See http://stackoverflow.com/a/42317158/, http://stackoverflow.com/questions/42459444/difference-between-i-i-and-i-i-1/ – guest271314 Mar 04 '17 at 04:38

4 Answers4

2

you are returning a new object each time with the values you are assigning to sitting and standing. So your increment/decrement is applied after the current value (0) is assigned. When I ran this I got { sitting: 0, standing: 0 } back and not NaN.

Changing prev.standing++ to prev.standing+= should resolve your issue.

And actually, you may want to consider just mutating the original accumulator you provided in this scenario. Renaming prev to accumulator, acc, or simply a might make this easier to reason about.

var deskTypes = desks.reduce(function(acc, curr) {
    if(curr.type === "sitting") {
        acc.sitting++
    }
    else if (curr.type === "standing") {
        acc.standing++;
    }
    return acc
}, { sitting: 0, standing: 0 });

or even better:

var deskTypes = desks.reduce(function(acc, curr) {
    acc[curr.type]++;
    return acc
}, { sitting: 0, standing: 0 });
Nate Good
  • 439
  • 4
  • 11
2

This question has nothing to do with Array.reduce(). You just need to understand how pre/post increment operators works.

Pre increments before assigning value. Post increments AFTER assigning value.

kctang
  • 10,894
  • 8
  • 44
  • 63
1

You are having different result due to pre increment(++x) and post increement operator (x++). When using preincrement operator, it increments value and return incremented value where as in post increment operator, it returns value and increemtn the value.

So, when using post increment operator in your code :

var deskTypes = desks.reduce(function(prev, curr) {
  if(curr.type === "sitting") {
 // prev.sitting is returning value and then incrementing which makes sitting value always 0
    return {sitting: prev.sitting++, standing: prev.standing}; 
  }

  if(curr.type === "standing") {
          // prev.standing is returning value and then incrementing which makes standing value always 0
      return {sitting: prev.sitting, standing: prev.standing++};
  }
}, { sitting: 0, standing: 0 });

If you change your way of assigning and have post incrementing value before assigning, then it works as per your expectation

var deskTypes = desks.reduce(function(prev, curr) {
  if(curr.type === "sitting") {

  prev.sitting++;// it returns and increments sitting value and hence it has incremented value
    return {sitting: prev.sitting, standing: prev.standing};
  }

  if(curr.type === "standing") {
  // it returns and increments standing value and hence it has incremented value
  prev.standing++;
      return {sitting: prev.sitting, standing: prev.standing};
  }
}, { sitting: 0, standing: 0 });
Akash KC
  • 16,057
  • 6
  • 39
  • 59
0

Hope this will be useful

var i = 1;
alert(i++); // shows 1
alert(i); // shows 2
i = 1;
alert(++i); // shows 2
alert(i); // shows 2

In your example prev.sitting & prev.standing is initially zero. So (prev.sitting)++ will be zero too

brk
  • 48,835
  • 10
  • 56
  • 78