Doubt about the reduce method in Javascript

Asked

Viewed 67 times

1

I took this small code from a material from the internet to print how many times a number repeats in the array, but I could not understand what was done, especially with this if and with the acumulado[atual].

Who can explain this piece of code better thank you and positive the answer.

const numeros = [7, 61, 36, 2, 17, 61, 114, 20, 2, 17, 7, 61]
const quantasVezesRepetiu = (acumulado, atual) => {
  if(!acumulado[atual]){
    acumulado[atual] = 0
  }
  acumulado[atual] += 1
  return acumulado
}
const vezes = numeros.reduce(quantasVezesRepetiu, {})
console.log(vezes)
  • The codic is wrong, the variable numero was not defined.

  • Actually the code is right, @Mariaeduarda...

  • @Mariaeduarda already edited, had made the publication without the array

1 answer

3


We must understand, first, that the Array.prototype.reduce works on an array. In this case, the array that will be reduced is the array itself under which we call the method reduce. Beyond the array (which is the "argument" this), reduce requires a reducing function and accepts an initial value.

In the example we are dealing with in this answer, we call reduce thus:

const result = [1, 2, 3, 1, 2, 1].reduce(countReducer, {});

So:

  • The array to be reduced will be [1, 2, 3, 1, 2, 1] ("argument" this).
  • The reducing function is countReducer (first argument of the method).
  • The starting value is {} (second argument of the method).

With that, to each array element [1, 2, 3, 1, 2, 1], the reducing function we pass will be called. The trick to "understand" is to know that the value that the reducer function returns will be used as the parameter accumulator for the next iteration. It is therefore important to define an initial accumulator in most cases.

  • Read to documentation, who has an example explaining step by step.

It is important to note that if you do not set initial accumulator, the first element of the array will be used as such. However, in that situation, according to the logic of what we want to do, this is not desirable.


Going now to the full code, we have:

function countReducer(accumulator, current) {
  // Caso o item da iteração atual ainda não tenha sido contabilizado.
  if (!accumulator[current]) {
    // Inicializamos o contador para o item da iteração atual como 0:
    accumulator[current] = 0;
  }

  // Incrementamos o contador para o item da iteração atual:
  accumulator[current] += 1;

  // Retornamos o acumulador para as próximas iterações:
  return accumulator;
}

const result = [1, 2, 3, 1, 2, 1].reduce(countReducer, {});
console.log(result);

1  | function countReducer(accumulator, current) {
2  |   // Caso o item da iteração atual ainda não tenha sido contabilizado.
3  |   if (!accumulator[current]) {
4  |     // Inicializamos o contador para o item da iteração atual como 0:
5  |     accumulator[current] = 0;
6  |   }
7  |
8  |   // Incrementamos o contador para o item da iteração atual:
9  |   accumulator[current] += 1;
10 |
11 |   // Retornamos o acumulador para as próximas iterações:
12 |   return accumulator;
13 | }
14 |
////                                                        ↓↓
15 | const result = [1, 2, 3, 1, 2, 1].reduce(countReducer, {});
16 | console.log(result);

Let’s understand what we want to happen and then understand the code above, line by line.

Assuming we have an array like [1, 2, 3, 1, 2, 1], we want to return an object with the amount of each element of the array, so:

{
  1: 3,
  2: 2,
  3: 1
}

And how the reduce will help us get there?

Starting from the first line to be executed (15), where we invoke the method reduce, note that we passed, as initial value, a literal object "empty" ({}). This is our object accumulator, only that he still finds himself "empty"!

From this, the reduce will call the function countReducer for each array element. So the parameter accumulator will be given by the function countReducer return in previous iteration (except in first iteration, in which accumulator is the empty object that we define in the second argument of the method).

Starting from the first iteration (in which {} is still empty), we need to add the elements with the respective counts. For this, we use the notation accumulator[current]. That’s the bracket notation for object access in Javascript.

In the specific case of the first iteration, for example, accumulator will still be empty. In this case, how current corresponds to the first element of the array, what we are doing is, this:

accumulator[current]

Is the same as:

accumulator[1]

That means we’re trying to access the property 1 in the object accumulator. In the case of first iteration, this property will not yet be defined, therefore the expression accumulator[current] (in the first iteration) return undefined.

In this case, as the counter has not yet been defined, we need to create a way to define the counter as 0 so that we can start counting for the element in question. That’s what the if (lines 3~6) is doing. It checks if the counter refers to the element (current) current has not yet been defined and if it has not actually been defined, arrow the current element counter to 0.

So on line 9 we can increase the count for the current element. Again we have the expression accumulator[current], which basically means:

Access, in the accumulator, the property whose key is (dynamically) current and increment 1, indicating that we went through this item once.

This same logic is processed for each element of the array.

  • Luiz, thank you so much for the answer, clarified some things, but this expression 'Accumulator[Current]' is still confused for me, I still can’t understand what value this expression is taking, and this was actually my main doubt.

  • @danielhcr22, I tried to edit the final part of the reply to explain a little better. Now gave to understand? :-)

  • Luiz, thank you for your answer, but I will take some time to assimilate this, reading your answer and some other materials I realized that I still have some doubts about objects, I will review this subject better and return here to read your answer, so it will be much more fluid understanding, thank you!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.