Reputation: 189
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
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
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
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
Reputation: 5472
So reduce
will take an array
and reduce it down to a single value. In your case, you're reduce
ing 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