GodAmongUs
GodAmongUs

Reputation: 75

Javascript reduce initialValue is empty object, what's the meaning of it?

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

Answers (3)

Ben Aston
Ben Aston

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

Marco
Marco

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

Mr. Polywhirl
Mr. Polywhirl

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

Related Questions