10 reduce tricks worth mastering

As a front-end developer, you must have been exposed to the reduce function. It is a powerful and practical array method. Mastering the use of reduce can improve development efficiency and code quality. The 10 techniques of reduce introduced in this article are worth having, which can save you from writing a lot of code!

The reduce method executes the provided callback iterator on each element of the array. It is passed the return value of the previous element computation, and the result is a single value that is the result of running the iterator over all the elements of the array.

The Iterator function iterates over the elements of the array one by one, and at each step the Iterator function adds the current array value to the result of the previous step until there are no more elements to add .

Grammar

The parameters include a callback function and an optional initial value, as follows:

array.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

  • callback (required): Execute the reducer function for each value in the array (except the first value if initialValue is not provided), including four parameters

    • accumulator (required): the return value of the accumulator callback; it is the accumulated value returned when the callback was called last time, the initial value can be defined by initialValue, the default is the array The first element value, The accumulator will hold the value of the previous operation, just like a static variable

    • currentValue (required): the element being processed in the array

    • index (optional): The index of the current element in the array being processed. If initialValue is provided, start at index 0, otherwise start at index 1.

      Note: If initialValue is not provided, reduce will execute the callback method from index 1, Skip first index. If initialValue is provided, start at index 0.

    • array (optional): The array on which reduce() was called

  • initialValue (optional): The value that is used as the first parameter when the callback function is called for the first time. If no initial value is provided, the first element in the array will be used. Calling reduce on an empty array with no initial value will report an error.

1. Calculate the maximum and minimum values of the array

There are many ways to get the maximum or minimum value of an array?

Using Math.max and Math.min

Using Math’s API is the easiest way.

const arrayNumbers = [-1, 10, 6, 5, -3];
const max = Math.max(...arrayNumbers); // 10
const min = Math.min(...arrayNumbers); // -3
console.log(`max=${max}`); // max=10
console.log(`min=${min}`); // min=-3

Using reduce

One line of code can achieve the same effect as the API of Math.

const arrayNumbers = [-1, 10, 6, 5, -3];
const getMax = (array) => array. reduce((max, num) => (max > num ? max : num));
const getMin = (array) => array. reduce((max, num) => (max < num ? max : num));

const max = getMax(arrayNumbers); // 10
const min = getMin(arrayNumbers); // -3
console.log(`max=${max}`); // max=10
console.log(`min=${min}`); // min=-3

Or written as a function:

const arrayNumbers = [-1, 10, 6, 5, -3];

const getMaxOrMin = (array, type = "min") =>
    type === "max"
        ? array.reduce((max, num) => (max > num ? max : num))
        : array.reduce((max, num) => (max < num ? max : num));

const max = getMaxOrMin(arrayNumbers, "max"); // 10
const min = getMaxOrMin(arrayNumbers, "min"); // -3
console.log(`max=${max}`); // max=10
console.log(`min=${min}`); // min=-3

2. Array summation and accumulator

Using reduce, you can easily implement the function of adding or accumulating multiple numbers.

// array summation
const sum = (...nums) => {<!-- -->
    return nums.reduce((sum, num) => sum + num);
};

// accumulator
const accumulator = (...nums) => {<!-- -->
    return nums.reduce((acc, num) => acc * num);
};
const arrayNumbers = [1, 3, 5];

console.log(accumulator(1, 2, 3)); // 6
console.log(accumulator(...arrayNumbers)); // 15

console.log(sum(1, 2, 3, 4, 5)); // 15
console. log(sum(...arrayNumbers)); // 9

3. Format search parameters

Getting search parameters for URLs is a frequently-handled function.

// url https://www.devpoint.cn/index.shtml?name=devpoint&id=100
// format search parameters
{<!-- -->
    name: "devpoint",
    id: "100",
}

Normal method

This is how most people use it.

const parseQuery = (search = window.location.search) => {<!-- -->
    const query = {<!-- -->};
    search
        .slice(1)
        .split(" &")
        .forEach((it) => {<!-- -->
            const [key, value] = it. split("=");
            query[key] = decodeURIComponent(value);
        });
    return query;
};
console.log(parseQuery("?name=devpoint & amp;id=100")); // { name: 'devpoint', id: '100' }

Using reduce

const parseQuery = (search = window. location. search) =>
    search
        .replace(/(^\?)|( & amp;$)/g, "")
        .split(" &")
        .reduce((query, it) => {<!-- -->
            const [key, value] = it. split("=");
            query[key] = decodeURIComponent(value);
            return query;
        }, {<!-- -->});

console.log(parseQuery("?name=devpoint & amp;id=100")); // { name: 'devpoint', id: '100' }

4. Deserialize search parameters

When you want to jump to a link and add some search parameters to it, the way of manual splicing is not very convenient. If there are many parameters to concatenate, it will be a disaster.

const searchObj = {
    name: "devpoint",
    id: 100,
    //...
};
const strLink = `https://www.devpoint.cn/index.shtml?name=${searchObj.name} & amp;age=${searchObj.id}`;
console.log(strLink); // https://www.devpoint.cn/index.shtml?name=devpoint & amp;age=100

reduce can easily solve this problem.

const searchObj = {<!-- -->
    name: "devpoint",
    id: 100,
    //...
};
const stringifySearch = (search = {<!-- -->}) =>
    Object. entries(search)
        .reduce(
            (t, v) => `${<!-- -->t}${<!-- -->v[0]}=${<!-- -->encodeURIComponent(v[1]) } & amp;`,
            Object.keys(search).length ? "?" : ""
        )
        .replace(/ & amp;$/, "");

const strLink = `https://www.devpoint.cn/index.shtml${<!-- -->stringifySearch(
    searchObj
)}`;
console.log(strLink); // https://www.devpoint.cn/index.shtml?name=devpoint & amp;age=100

5. Flatten multi-level nested array

How to flatten multilevel nested arrays?

const array = [1, [2, [3, [4, [5]]]]];
const flatArray = array. flat(Infinity);

console.log(flatArray); // [ 1, 2, 3, 4, 5 ]

If the running environment supports the method flat , you can use it directly. If not, you can use reduce to achieve the same function as flat.

const array = [1, [2, [3, [4, [5]]]]];

const flat = (arrayNumbers) =>
    arrayNumbers.reduce(
        (acc, it) => acc. concat(Array. isArray(it) ? flat(it) : it),
        []
    );
const flatArray = flat(array);

console.log(flatArray); // [ 1, 2, 3, 4, 5 ]

6. Count the number of array members

How to count the number of each member in an array? That is, count the number of repeated elements.

const count = (array) =>
    array.reduce(
        (acc, it) => (acc. set(it, (acc. get(it) || 0) + 1), acc),
        newMap()
    );
const array = [1, 2, 1, 2, -1, 0, "0", 10, "10"];
console. log(count(array));

The data type Map is used here. For this data type in JavaScript, if you are interested, you can read the following:

Map of JavaScript data structure

The output of the above code is as follows:

Map(7) {
  1 => 2,
  2 => 2,
  -1 => 1,
  0 => 1,
  '0' => 1,
  10 => 1,
  '10' => 1
}

7. Get multiple properties of an object

This is a relatively common scenario in project development. Get the back-end data through the API, and the front-end often only needs to get part of the data.

// an object with many properties
const obj = {<!-- -->
    a: 1,
    b: 2,
    c: 3,
    d: 4,
    e: 5,
    //...
};
// just want to get some properties on it to create a new object
const newObj = {<!-- -->
    a: obj.a,
    b: obj.b,
    c: obj.c,
    d: obj.d,
    //...
};

At this time, you can use reduce to solve it.

/**
 *
 * @param {*} obj original object
 * @param {*} keys The list of attribute values that need to be obtained, in the form of an array
 * @returns
 */
const getObjectKeys = (obj = {<!-- -->}, keys = []) =>
    Object.keys(obj).reduce(
        (acc, key) => (keys. includes(key) & amp; & amp; (acc[key] = obj[key]), acc),
        {<!-- -->}
    );

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 }

8. Reverse string

Reversing a string is one of the most frequently asked JavaScript questions in interviews.

const reverseString = (string) => {<!-- -->
    return string.split("").reduceRight((acc, s) => acc + s);
};
const string = "devpoint";
console.log(reverseString(string)); // tniopved

9. Array deduplication

reduce is also very easy to implement array deduplication.

const array = [1, 2, 1, 2, -1, 10, 11];
const uniqueArray1 = [...new Set(array)];
const uniqueArray2 = array. reduce(
    (acc, it) => (acc. includes(it) ? acc : [...acc, it]),
    []
);

console.log(uniqueArray1); // [ 1, 2, -1, 10, 11 ]
console.log(uniqueArray2); // [ 1, 2, -1, 10, 11 ]

10. Simulation method flat

Although the current JavaScript has a native method that has realized the function of flattening deeply nested arrays, how can the flattening function be completely realized? The following is to use reduce to realize its function:

// Expand one layer by default
Array.prototype.flat2 = function (n = 1) {<!-- -->
    const len = this. length;
    let count = 0;
    let current = this;
    if (!len || n === 0) {<!-- -->
        return current;
    }
    // Check if there is currently an array item
    const hasArray = () => current.some((it) => Array.isArray(it));
    // Expand one layer after each loop
    while (count + + < n & amp; & amp; hasArray()) {<!-- -->
        current = current. reduce((result, it) => result. concat(it), []);
    }
    return current;
};
const array = [1, [2, [3, [4, [5]]]]];
// Expand a layer
console.log(array.flat()); // [ 1, 2, [ 3, [ 4, [ 5 ] ] ] ]
console.log(array.flat2()); // [ 1, 2, [ 3, [ 4, [ 5 ] ] ] ]
// Expand all
console.log(array.flat(Infinity)); // [ 1, 2, 3, 4, 5 ]
console.log(array.flat2(Infinity)); // [ 1, 2, 3, 4, 5 ]