DEV Community

Cover image for 5 ways to use the reduce method in JS
Matvey Romanov
Matvey Romanov

Posted on

5 ways to use the reduce method in JS

The modern JavaScript standard provides many methods for "smart" brute force for arrays. Among the most popular are forEach, for or for...of. If you need to iterate over the array and return data for each element, map is suitable.

In case you need to walk through the array and, for example, summarize all the values, find the average or perform any intermediate actions, it is better to use the reduce method.

In what scenarios it can be used - in this article.

Reduce collapses the array to one value (reducets). This value can be any type of data - both primitive and composite, for example, an array.

The method accepts two arguments:

  • callback function performed to run each element in the array;
  • initial value of initialValue. Callback also accepts two arguments: accumulator, which returns the callback function after visiting another element, and the current element in the currentValue loop.

Let's consider several non-obvious applications of the reduce method that will help to adhere to the write less, do more principle.

Minimum and maximum value in the array

To find the minimum and maximum values, you can use the Math API, for example:

const array = [-11, 2, 21, 3];
const max = Math.max(...array); // 21
const min = Math.min(...array); // -11
Enter fullscreen mode Exit fullscreen mode

But when using large arrays (~10^7), you may encounter errors. You can eliminate these problems and get the desired result using the reduce method.

const array = [-11, 2, 21, 3];
const max = array.reduce((max, num) => (max > num ? max : num)); // 21
const min = array.reduce((min, num) => (min < num ? min : num)); // -11
Enter fullscreen mode Exit fullscreen mode

You may need to parse the parameters in the GET URL and add them to an object.

const parseQuery = () => {
  const url = new URL("https://ranbow1.xyz?name=hello&title=world");
  const search = url.search;
  let query = {};
  search
    .slice(1)
    .split("&")
    .forEach((item) => {
      const [key, value] = item.split("=");
      query[key] = decodeURIComponent(value);
    });
  return query;
};
// {name: "hello", title: "world"}
Enter fullscreen mode Exit fullscreen mode

But using the reduce method, everything becomes clearer and more predictable:

const parseQuery = () => {
  const url = new URL("https://ra1nbow.xyz?name=hello&title=world");
  const search = url.search;
  return search
    .replace(/(^?)|(&$)/g, "")
    .split("&")
    .reduce((query, item) => {
      const [key, value] = item.split("=");
      query[key] = decodeURIComponent(value);
      return query;
    }, {});
};
// {name: "hello", title: "world"}
Enter fullscreen mode Exit fullscreen mode

Here's how it works:

  1. Get search parameters from the URL - https://ra1nbow.xyz? name=hello&title=world
const search = url.search;  // ?name=hello&title=world
Enter fullscreen mode Exit fullscreen mode
  1. Remove unnecessary characters
search.replace(/(^?)|(&$)/g, "");
//?name=hello&title=world => name=hello&title=world
Enter fullscreen mode Exit fullscreen mode
  1. We use reduce to collect parameters into an object

Deserialization of parameters

In this example, the situation is the opposite. If you need to add a set of parameters to the link, it is not very convenient to use concatenation (gluing lines), especially if there are tens or hundreds of such parameters. Because of this, the readability of the code drops significantly, the line size increases with each new parameter, which creates difficulties for further support.

const searchObj = {
  name: 'hello',
  title: 'world',
}; // many others parameters
const link = `https://ra1nbow.xyz?name=${searchObj.name}&age=${searchObj.title}`;
Enter fullscreen mode Exit fullscreen mode

You can correct the situation using the reduce method. First of all, we write the function:

const stringifySearch = (search = {}) => {
  return Object.entries(search)
    .reduce(
      (t, v) =>     `${t}${v[0]}=${encodeURIComponent(v[1])}&`,
      Object.keys(search).length ? '?' : ''
    )
    .replace(/&$/, '');
};
Enter fullscreen mode Exit fullscreen mode

Next, we take the object from the previously described example and apply it:

const searchObj = {
  name: 'hello',
  title: 'world',
}; // many others parameters
const search = stringifySearch(searchObj);
const link = `https://ra1nbow.xyz${search}`; // https://ra1nbow.xyz?name=hello&title=world
Enter fullscreen mode Exit fullscreen mode

Now you don't have to worry that when you change the object, the subsequent code will not work correctly.

Selection of unique elements of the array

It's simple: we go through the array and look for if there is already such a meaning in it. If not, we add it, and if there is one, we go further. Thus, the output will be an array of only unique values.

const someArray = [1, 2, 1, 2, -1, 10, 11];
const uniqueArray = someArray.reduce(
  (acc, item) => (acc.includes(item) ? acc : [...acc, item]),
  []
); // [1, 2, -1, 10, 11]
Enter fullscreen mode Exit fullscreen mode

Determining the number of identical elements of the array

To get the number of each element in the array, we additionally use Map - this is a collection of key value, as well as Object.

The main difference is that in Map we will be able to work with an array that uses values of different types (numbers/rows).

const count = (array) => {
  return array.reduce(
    (acc, item) => (acc.set(item, (acc.get(item) || 0) + 1), acc),
    new Map()
  );
};
const array = [1, 2, 1, 2, -1, 0, 0, 10, 10, 6];
console.log(count(array)); // Map(6) {1 => 2, 2 => 2, -1 => 1, 0 => 2, 10 => 2, 6 => 1}
Enter fullscreen mode Exit fullscreen mode

Getting multiple object properties

Such a scenario quite often occurs in everyday work. Let's look at an example.

We have an object with many properties:

const obj = {
  a: 1,
  b: 2,
  c: 3,
  d: 4,
  e: 5
  // ...
}
Enter fullscreen mode Exit fullscreen mode

We want to get some properties of the previous object and create a new one:

const newObj = {
  a: obj.a,
  b: obj.b,
  c: obj.c,
  d: obj.d
  // ...
}
Enter fullscreen mode Exit fullscreen mode

It doesn't seem to be very effective, does it?

Let's write a small helper that will make it easier for us to solve the problem:

const getObjectKeys = (obj = {}, keys = []) => {
  return Object.keys(obj).reduce(
    (acc, key) => (keys.includes(key) && (acc[key] = obj[key]), acc),
    {}
  );
};
Enter fullscreen mode Exit fullscreen mode

And, of course, let's check how it all works:

const obj = {
  a: 1,
  b: 2,
  c: 3,
  d: 4,
  e: 5
  // ...
}
const newObj = getObjectKeys(obj, [ 'a', 'b', 'c', 'd' ])
console.log(newObj) // {a: 1, b: 2, c: 3, d: 4}
Enter fullscreen mode Exit fullscreen mode

This is only part of the possible scenarios for applying the method in everyday tasks. I hope you found something interesting for yourself.

Thank you for your attention and happy coding!

My Github <3

Latest comments (2)

Collapse
 
fruntend profile image
fruntend

Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up 🫰

Collapse
 
ra1nbow1 profile image
Matvey Romanov

Thanks 😁