techalicious
techalicious

Reputation: 441

Javascript: Reduce function with ||

Can someone explain the following code? inputWords is supposed to be an array containing various words and this function is supposed to return an array containing the number of times a word appears in inputWords.

ie. var inputWords = ['Apple', 'Banana', 'Apple', 'Durian', 'Durian', 'Durian']

console.log(countWords(inputWords))
// =>
// {
//   Apple: 2,
//   Banana: 1,
//   Durian: 3
// }

I understand what the Reduce function does, but what is resultObj[word] = ++resultObj[word] || 1; doing?

Thanks so much :)

function countWords(inputWords) {
  return inputWords.reduce(function(resultObj, word) {
    resultObj[word] = ++resultObj[word] || 1;
    return resultObj;
  }, {});
}

module.exports = countWords;

Upvotes: 2

Views: 458

Answers (3)

Christian Landgren
Christian Landgren

Reputation: 13783

I would write:

resultObj[word] = (resultObj[word] || 0) + 1;

Upvotes: 1

Tom Fenech
Tom Fenech

Reputation: 74685

The code attempts to assign to a key (that may not yet exist) an incremented value (of a key that may not yet exist), of if that it that is falsey, it assigns a 1.

This is called short-circuit evaluation. Given a = b || c, if b is truthy, c never gets evaluated so a takes on the value of b. If b is falsey, c is evaluated and assigned to a instead. In your case, when the key doesn't exist, ++resultObj[word] is falsey.

In my humble opinion, I think that it would have been a clearer statement of the author's intention if they had instead done:

if (word in resultObj) {
    ++resultObj[word];
}
else {
    resultObj[word] = 1;
}

or even:

resultObj[word] = word in resultObj ? resultObj[word] + 1 : 1;

either of which would have saved you the bother of asking this question.

Upvotes: 3

paolobueno
paolobueno

Reputation: 1708

It's 'defaulting' a non-existent key in resultObj to 1.

Javascript's || will actually return the first (leftmost) truthy value out of a comparison, so for a nonexistant value added one by the preincrement operator such as ++resultObj['banana'] returns NaN, which is falsey, and the || operator will replace it with 1.

Edit: See http://nfriedly.com/techblog/2009/07/advanced-javascript-operators-and-truthy-falsy/

Upvotes: 1

Related Questions