In-depth understanding of the all-powerful Reducer

  html5, javascript, node.js, Programmer

Translation: Liu Xiaoxi

Original link:https://css-tricks.com/unders …

More articles to stamp: https://github.com/YvetteLau/ …

There are some small partners, for JavaScriptreduceThe method is not fully understood. Let’s look at the following two pieces of code:

const nums = [1, 2, 3];
let value = 0;

for (let i = 0; i < nums.length; i++) {
    value += nums[i];
}
const nums = [1, 2, 3];
const value = nums.reduce((ac, next) => ac + next, 0);

These two pieces of code are functionally equivalent and are the sum of all the numbers in the array, but there are some conceptual differences between them. Let’s look at it firstreducerBecause they are powerful and important in programming. There are hundreds of articles aboutreducerIn the end, I will link the articles I like.

reducerWhat is it?

To understandreducerThe first and most important point of is that it always returns a value, which can be a number, string, array or object, but it can always be only one.reducerIt is suitable for many scenarios, but they are especially suitable for applying a logic to a set of values and finally obtaining a single result.

In addition, it should be noted that:reducerIn essence, it will not change your initial value; On the contrary, they will return something else.

Let’s review the first example so that you can see what is happening here. Let’s look at the following gif:

clipboard.png

Watching gif may help us all, but we still need to return to the code:

const nums = [1, 2, 3];
let valu
![clipboard.png](/img/bVbv3AR)
let i = 0; i < nums.length; i++) {
    value += nums[i];
}

arraynums([1,2,3]), the first value of each number in the array will be added to thevalue(0)。 We traverse the array and add each of its entries to thevalue.

Let’s try different ways to achieve this function:

const nums = [1, 2, 3];
const initialValue = 0;

const reducer = function (acc, item) { 
    return acc + item;
}

const total = nums.reduce(reducer, initialValue);

Now we have the same array, but this time we won’t change the initial valuevalue)。 Here, we have an initial value used only at the beginning. Next, we can create a function that accepts an accumulator (acc) and an item (item)。 Accumulator is the cumulative value returned in the last call (orinitialValueIs the input value for the next callback. In this example, you can imagine it as a snowball rolling down a mountain. When it grows by the size of each value it eats, it will eat every value in its path.

clipboard.png

We will use.reduce()To receive this function and start with the initial value. You can use the arrow function abbreviation:

const nums = [1, 2, 3];
const initialValue = 0;

const reducer = (acc, item) => { 
    return acc + item;
}

const total = nums.reduce(reducer, initialValue);

To further shorten the code length, we know the arrow function, in no.{}When, by defaultreturn;

const nums = [1, 2, 3];
const initialValue = 0;

const reducer = (acc, item) => acc + item;

const total = nums.reduce(reducer, initialValue);

Now we can apply this function where it is called, or we can directly set the initial value as follows:

const nums = [1, 2, 3];

const total = nums.reduce((acc, item) => acc + item, 0);

Accumulator can be a daunting term, so when we apply logic to callback calls, you can think of it as the current state of the array.

Call stack

If it is not clear what happened, let’s record the situation of each iteration.reduceThe callback function used will run for each item in the array. The following demonstration will help to illustrate this point more clearly. I used a different array ([1, 3, 6]), because the same number and index can be confusing.

const nums = [1, 3, 6];

const reducer4 = function (acc, item) { 
    console.log(`Acc: ${acc}, Item: ${item}, Return value: ${acc + item}`);
    return acc + item;
}
const total4 = nums.reduce(reducer4, 0);

When we execute this code, we will see the following output on the console:

Acc: 0, Item: 1, Return value: 1
Acc: 1, Item: 3, Return value: 4
Acc: 4, Item: 6, Return value: 10

The following is a more intuitive decomposition:

clipboard.png

  1. Accumulator (accFrom the initial value (initialValue): 0
  2. And then the firstitemIs 1, so the return value is 1(0+1=1)
  3. 1 becomes accumulator on next call
  4. Now our accumulator is 1 (acc),item(the second item in the array) is 3
  5. The return value becomes 4(1+3=4)
  6. 4 becomes accumulator on next call, next item on callitemIt’s 6
  7. The result is 10(4+6=10), which is our final value, because 6 is the last item in the array

Simple example

Now that we have mastered this, let’s take a lookreducerSome common and useful things that can be done.

How many x’s do we have?

Suppose you have an array of numbers and want to return an object that reports the number of times these numbers appear in the array. Please note that this also applies to strings.

const nums = [3, 5, 6, 82, 1, 4, 3, 5, 82];

const result = nums.reduce((tally, amt) => {
    tally[amt] ? tally[amt]++ : tally[amt] = 1;
    return tally;
}, {});

console.log(result);
//{ '1': 1, '3': 2, '4': 1, '5': 2, '6': 1, '82': 2 }

At first, we had an array and the objects to be put into it. InreducerIn, we first determine whether this item exists in the accumulator, and if so, add 1. If it does not exist, add this item and set it to 1. Finally, please return the number of occurrences of each item. Then, we runreduceFunction, passing at the same timereducerAnd initial values.

Gets an array and converts it to an object that displays certain conditions

Assuming we have an array, we want to create an object based on a set of conditions.reduceIt is very applicable here! Now, we want to create an object from any number item in the array and display both odd and even versions of the number.

const nums = [3, 5, 6, 82, 1, 4, 3, 5, 82];

// we're going to make an object from an even and odd
// version of each instance of a number
const result = nums.reduce((acc, item) => {
  acc[item] = {
    odd: item % 2 ? item : item - 1,
    even: item % 2 ? item + 1 : item
  }
  return acc;
}, {});

console.log(result);

Console output results:


{ '1': { odd: 1, even: 2 },
  '3': { odd: 3, even: 4 },
  '4': { odd: 3, even: 4 },
  '5': { odd: 5, even: 6 },
  '6': { odd: 5, even: 6 },
  '82': { odd: 81, even: 82 } 
}

When we traverse each item in the array, we create an attribute for even and odd numbers, and based on an inline condition with modulus operator, we either store the number or increment it by 1. Modulus operator is very suitable for this because it can quickly check even or odd numbers-if it can be divided exactly by two, it is even, if not, it is odd.

Other resources

At the top, I mentioned some other convenient articles, which are helpful for getting familiar with them.reducerThe role of. The following are my favorites:

  1. MDN documentThis is very useful. To be honest, this is one of their best posts, and they also described in more detail what would happen if you did not provide an initial value, which we did not mention in this article.
  2. Coding Train
  3. A Drip of JavaScript

Thank you for your friends’ willingness to spend precious time reading this article. If this article gives you some help or inspiration, please don’t be stingy with your praise and Star. Your affirmation is my greatest motivation to move forward.https://github.com/YvetteLau/ …

I recommend paying attention to my public number.

clipboard.png