Here's an MDN example of Array.prototype.reduce()
I'm not quite understand:
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];
const countedNames = names.reduce((allNames, name) => {
const currCount = allNames[name] ?? 0;
return {
...allNames,
[name]: currCount 1,
};
}, {});
// countedNames is:
// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
What do allNames[name] ?? 0
and ...allNames,
mean here, and how does it generate the result? Thank you!
I searched the ...
and ??
meaning, but still can't understand the use of allNames[name]
? is this same with array[index]
?
CodePudding user response:
const currCount = allNames[name] ?? 0
This is a use of the Nullish coalescing operator. It means that the variable currCount
will first try to be assigned the value of allNames[name]
. However, if that results in a "nullish" value (in this case undefined
because there hasn't been anything assigned in allNames
for a specific name
), then the variable gets assigned to 0
.
return {
...allNames,
};
This is a use of the spread operator and object destructuring. It means that the a new object will be created with all the properties (keys and values) of the old allNames
object.
[name]: currCount 1,
This part says to create a new property with the key as a specific name and the value as the current count plus one. Combined with the snippet above, this will create a new object that's the same as allNames
, except that the property with the key name
will get overwritten, with the new value having an updated count.
CodePudding user response:
Your .reduce()
function "reduces" (converts) the input Array into an Object {}
Since the object has no properties (it's "empty") you cannot increment a value to a non-existing property-value.
In the first iteration allNames[name]
is undefined
.
const currCount = allNames[name] ?? 0;
You cannot later increment undefined
therefore the Nullish coalescing operator ??
makes sure to fallback that undefined
the value to 0
- and stores it into currCount
.
return {
...allNames,
[name]: currCount 1,
};
The above just uselessly destructures the ...allNames
object into a new Object (that is then returned and reused in the next iteration as a modified allNames
) - and overrides the number of a specific property Name.
Here's a different (better, more legible) remake of the same:
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];
const countedNames = names.reduce((ob, name) => {
ob[name] ??= 0; // if undefined, set that property and set value of 0
ob[name] = 1; // Increment value by 1
return ob;
}, {});
console.log(countedNames)
Which without using any fancy code is the same as doing:
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];
const countedNames = names.reduce((ob, name) => {
if (!ob.hasOwnProperty(name)) {
ob[name] = 0;
}
ob[name] = 1; // Increment it
return ob;
}, {});
console.log(countedNames)
which, without the .reduce() it's done like:
const names = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];
const ob = {};
names.forEach((name) => {
if (!ob.hasOwnProperty(name)) {
ob[name] = 0;
}
ob[name] = 1; // Increment it
});
console.log(ob)