You Ma
You Ma

Reputation: 189

How does reduce work here?

I was reading the documentation of the reduce function in javascript and I got stuck at this example.

var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function(allNames, name) {

    if (name in allNames) {
        allNames[name]++;
    } else {
        allNames[name] = 1;
    }

    return allNames;
}, {});

console.log(countedNames);

How does it output :

{ 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }

instead of

{ 2,1,1,1}

Upvotes: 1

Views: 334

Answers (4)

dtburgess
dtburgess

Reputation: 613

You are passing an anonymous function and an empty object to the reduce method. If you look at the docs on MDN for reduce: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce

You can see that it accepts a callback function and an initial value. In this case you are passing an empty object {} as the initial value (see second to last line)

The reduce method then "applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value."

This single value starts out as the the empty object, and then properties get added and incremented in this object based on the conditional logic inside the body of the callback function.

Your line:

allNames[name] = 1

serves to create a property with the name name and assigns the property the value of 1.

This line:

allNames[name] += 1;

Simple increments an existing property.

I would further suggest that the code example lacks formatting that would further clarify the code:

var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var obj = {};

var countedNames = names.reduce(function(allNames, name) {
  if (name in allNames) {
    allNames[name]++;
  } else {
    allNames[name] = 1;
  }

  return allNames;
}, obj);

console.log(countedNames);

Upvotes: 1

hackerrdave
hackerrdave

Reputation: 6706

Array.prototype.reduce() is an accumulator function - it will iterate through all elements in an array and perform some work on them to reduce them down to a single value. In this example, we initialize our single value to be an empty object, allnames = {}. As we iterate through the names, we check if that name already exists in the object as a key - if it does, then we increment the count, if it does not then we initialize that key value pair to be <name>: 1:

var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
var countedNames = names.reduce(function(allNames, name) {
  if (name in allNames) { //first time through, allNames = {}
    allNames[name]++; //if name is present as key in allNames object, increment the value by 1
  } else {
    allNames[name] = 1; //first time through now allNames = {'Alice': 1 }
  }

  return allNames;
}, {}); //initialize allNames with empty object

Upvotes: 0

Andrew Willems
Andrew Willems

Reputation: 12458

The reduce function begins with a starting value to which subsequent "reductions" of incoming data will provide modifications. In this case that starting value is {}, i.e. an object literal, from the 2nd last line of your code. The gradually accumulating value to which all the new modifications will be applied is, in this case, called allNames. When the reduce function does something to allNames[name], it is doing something to a property of the allNames object whose key is name, e.g. 'Alice'. Thus, for instance, the first time Alice's name is encountered, the property whose key is Alice is created and is assigned the value 1. This continues through the original input, eventually producing the end result you indicate.

Upvotes: 0

JohanP
JohanP

Reputation: 5472

So reduce will take an array and reduce it down to a single value. In your case, you're reduceing an array of names down to a hash that contains the names and the count of how many times that name exists in your array. The last argument of reduce is the initial start value. In this case you are giving it an empty object. This object is represented by allNames in your callback function. So for every name in your array, you check in allNames if that name already exists. If it does, then increment the count for that name otherwise set it to 1.

Upvotes: 0

Related Questions