bakrall
bakrall

Reputation: 633

Counting with reduce() - where the values come from?

While learning to filter out values which appear only once in array, I came across a very useful piece of code which I adjusted for my needs. I started to analyze how the counting of repetition of one value is performed. Below I have a function which does the counting.

function countInstancesOfAppearance(word) {
    var letters = word.split('');

    return countLetters = letters.reduce(function(object, key) {
      object[key] = object[key] ? object[key] + 1 : 1;
      return object;
    }, {});
}

And the result is: {l: 1, a: 1, s: 2, o: 1}.

However, I cannot understand what is going on behind the object[key] + 1 : 1. For me much more clearer would be to have the function written in a following way:

function countInstancesOfAppearance(word) {
    var letters = word.split('');

    return countLetters = letters.reduce(function(object, key) {
      if (object[key] = object[key]) {
        object[key] = object[key] + 1; 
      } else {
        object[key] = 1;
      }

      return object;
    }, {});
}

To describe my reasoning better:

var obj = {};
obj.cat = ""; // obj = {cat: ""};
obj.cat + 1 // in console, it gives 1, but the object continues to be obj = {cat: ""};
obj.cat = 1 // only now we have obj = {cat: 1};
obj.cat + 1 // the object continues to be obj = {cat: 1};
obj.cat = obj.cat + 1 //only now we have obj = {cat: 2};

So can you please explain to me how it happens that reduce() method takes advantage of obj.cat + 1 or just 1 in the following conditional object[key] = object[key] ? object[key] + 1 : 1; to make the proper assignments?

Here is the code with console.logs:

function countInstancesOfAppearance(word) {
    var letters = word.split('');

    return countLetters = letters.reduce(function(object, key) {
    console.log("object", object);
    console.log("key", key);
    console.log("object[key] = object[key]", object[key] = object[key]);
      object[key] = object[key] ? object[key] + 1 : 1;
      return object;
    }, {});
}

And the output of it:

enter image description here

Upvotes: 0

Views: 339

Answers (2)

AuxTaco
AuxTaco

Reputation: 5171

The conditional operator has higher precedence than the assignment operator, so

object[key] = object[key] ? object[key] + 1 : 1;

is equivalent to

object[key] = (object[key] ? object[key] + 1 : 1);

object[key] is set to 1 if it was undefined or 0 (as those values are falsy), and incremented in most other cases.

Upvotes: 1

FredG
FredG

Reputation: 276

Check the ternary operator documentation.

object[key] = object[key] ? object[key] + 1 : 1;

can be rewritten

if (object[key]) {                  // object[key] alreay exists
    object[key] = object[key] + 1;  // increment its value
} else {
    object[key] = 1;                // object[key] does not exist, initialize it with 1
}

Upvotes: 1

Related Questions