Reputation: 75
In MDN Array.prototype.reduce() , what's the meaning of allNames[name]
? allNames
should be {}
first, but if object is empty, allNames[name] = 1
equal to {}['Alice'] = 1
? how can it become { 'Alice': 1}
,
I'm so confused.
Counting instances of values in an object
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;
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
Upvotes: 5
Views: 3286
Reputation: 55729
Array#reduce
is an aggregation or accumulator function. This means it takes a collection of items (names
) and boils it down to a single "accumulated" value (allNames
).
names.reduce(function (allNames, name) { // `allNames` is the accumulated value, `name` is the current item in `names`
if (name in allNames) {
allNames[name]++;
}
else {
allNames[name] = 1;
}
return allNames;
}, {}); // The empty object here is the initial value of the accumulated value
So this function creates an accumulated value that is an object with a key corresponding to each name in names
, and values corresponding to the frequency of that name
in names
.
Finally: note that objects have an index notation for property access/creation (very similar to arrays!). So the following means "if such a property does not already exist on object allNames
, create a property with a name that is the value of variable name
, and assign the value 1
to its value:
allNames[name] = 1
Upvotes: 4
Reputation: 2892
From the docs you provided:
The reducer function takes four arguments: Accumulator (acc) Current Value (cur) Current Index (idx) Source Array (src)
So the first variable is the accumulator, a variable that will hold accumulated values that you eventually will calculate, like in this example you are accumulating names.
Upvotes: 1
Reputation: 48600
The reduce function above can be rewritten into the following function.
This streamlined version shows that we are modifying the result (starts with {}
) by incrementing the value for the name
.
If result[item]
is undefined, we use zero.
const names = [ 'Alice', 'Bob', 'Tiff', 'Bruce', 'Alice' ];
const frequencyMap = (items) => items.reduce((result, item) =>
({ ...result, [item]: (result[item] || 0) + 1 }), {});
console.log(frequencyMap(names));
.as-console-wrapper { top: 0; max-height: 100% !important; }
Here is the really-long version without reduce.
const names = [ 'Alice', 'Bob', 'Tiff', 'Bruce', 'Alice' ];
const frequencyMap = {};
for (let i = 0; i < names.length; i++) {
const name = names[i],
prev = frequencyMap[name];
if (prev !== undefined) {
frequencyMap[name] += 1; // Increment value by 1
} else {
frequencyMap[name] = 1; // Initial value
}
}
console.log(frequencyMap);
.as-console-wrapper { top: 0; max-height: 100% !important; }
Upvotes: -1