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
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
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"}
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"}
Here's how it works:
- Get search parameters from the URL - https://ra1nbow.xyz? name=hello&title=world
const search = url.search; // ?name=hello&title=world
- Remove unnecessary characters
search.replace(/(^?)|(&$)/g, "");
//?name=hello&title=world => name=hello&title=world
- 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}`;
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(/&$/, '');
};
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
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]
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}
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
// ...
}
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
// ...
}
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),
{}
);
};
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}
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!
Top comments (2)
Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up 🫰
Thanks 😁