25 advanced uses of JS array reduce that you must know

25 advanced uses of JS array reduce that you must know

Preface

Reduce is one of the new conventional array methods added in ES5. Compared with forEach, filter and map, it seems to be somewhat neglected in actual use. It is found that people around me rarely use it, which leads to the gradual burial of such a powerful method.

If you use reduce often, how can you miss such a useful one! I still have to take it out of the dust, wipe it clean, and present its advanced uses to everyone. Such a useful method should not be buried by the public.

The following is a brief description of the syntax of reduce. For details, see the relevant description of reduce() on MDN.

  • Definition: Executes a custom accumulator on each element in an array and aggregates the results into a single return value
  • Format: array.reduce((t, v, i, a) => {}, initValue)
  • parameter
    • callback: callback function (required)
    • initValue: initial value (optional)
  • Callback function parameters
    • total(t): The return value of the accumulator after the calculation is completed (required)
    • value(v): current element (required)
    • index(i): the index of the current element (optional)
    • array(a): the array object to which the current element belongs (optional)
  • process
    • Use t as the initial value of the cumulative result. If t is not set, the first element of the array is used as the initial value.
    • Start traversal, use the accumulator to process v, accumulate the mapping results of v to t, end the loop, and return t
    • Enter the next loop and repeat the above operation until the last element of the array
    • End the traversal and return the final t

The essence of reduce is to apply the accumulator to the array members one by one, and use the value of the previous output as the value of the next input. Let's take a simple example to see the calculation results of reduce.

const arr = [3, 5, 1, 4, 2];
const a = arr.reduce((t, v) => t + v);
// Equivalent to const b = arr.reduce((t, v) => t + v, 0);

It doesn’t matter if you don’t understand the code very well. You should be able to understand it by posting a GIF of the function of reduce.

Reduce is essentially an accumulator function that performs custom accumulation on array members through a user-defined accumulator to obtain a value generated by the accumulator. In addition, reduce has a younger brother reduceRight. The functions of the two methods are actually the same, except that reduce is executed in ascending order, while reduceRight is executed in descending order.

Calling reduce() and reduceRight() on an empty array will not execute its callback function, so reduce() is considered invalid for an empty array.

Advanced Usage

The above simple example alone is not enough to explain what reduce is. To demonstrate the power of reduce, I provide 25 scenarios for you to apply the advanced usage of reduce. Some advanced usages may need to be combined with other methods to achieve, which provides more possibilities for the diversification of reduce.

The writing style of some sample codes may be a bit sloppy. If you are not used to it, you can sort it out according to your own habits.

Accumulate and multiply

function Accumulation(...vals) {
    return vals.reduce((t, v) => t + v, 0);
}

function Multiplication(...vals) {
    return vals.reduce((t, v) => t * v, 1);
}
Accumulation(1, 2, 3, 4, 5); // 15
Multiplication(1, 2, 3, 4, 5); // 120

Weighted sum

const scores = [
    { score: 90, subject: "chinese", weight: 0.5 },
    { score: 95, subject: "math", weight: 0.3 },
    { score: 85, subject: "english", weight: 0.2 }
];
const result = scores.reduce((t, v) => t + v.score * v.weight, 0); // 90.5

Instead of reverse

function Reverse(arr = []) {
    return arr.reduceRight((t, v) => (t.push(v), t), []);
}
Reverse([1, 2, 3, 4, 5]); // [5, 4, 3, 2, 1]

Replace map and filter

const arr = [0, 1, 2, 3];

// Replace map: [0, 2, 4, 6]
const a = arr.map(v => v * 2);
const b = arr.reduce((t, v) => [...t, v * 2], []);

// Replace filter: [2, 3]
const c = arr.filter(v => v > 1);
const d = arr.reduce((t, v) => v > 1 ? [...t, v] : t, []);

// Replace map and filter: [4, 6]
const e = arr.map(v => v * 2).filter(v => v > 2);
const f = arr.reduce((t, v) => v * 2 > 2 ? [...t, v * 2] : t, []);

Replace some and every

const scores = [
    { score: 45, subject: "chinese" },
    { score: 90, subject: "math" },
    { score: 60, subject: "english" }
];

// Replace some: at least one qualified const isAtLeastOneQualified = scores.reduce((t, v) => t || v.score >= 60, false); // true

// Replace every: all qualified const isAllQualified = scores.reduce((t, v) => t && v.score >= 60, true); // false

Array Splitting

function Chunk(arr = [], size = 1) {
    return arr.length ? arr.reduce((t, v) => (t[t.length - 1].length === size ? t.push([v]) : t[t.length - 1].push(v), t), [[]]) : [];
}
const arr = [1, 2, 3, 4, 5];
Chunk(arr, 2); // [[1, 2], [3, 4], [5]]

Array filtering

function Difference(arr = [], oarr = []) {
    return arr.reduce((t, v) => (!oarr.includes(v) && t.push(v), t), []);
}
const arr1 = [1, 2, 3, 4, 5];
const arr2 = [2, 3, 6]
Difference(arr1, arr2); // [1, 4, 5]

Array filling

function Fill(arr = [], val = "", start = 0, end = arr.length) {
    if (start < 0 || start >= end || end > arr.length) return arr;
    return [
        ...arr.slice(0, start),
        ...arr.slice(start, end).reduce((t, v) => (t.push(val || v), t), []),
        ...arr.slice(end, arr.length)
    ];
}
const arr = [0, 1, 2, 3, 4, 5, 6];
Fill(arr, "aaa", 2, 5); // [0, 1, "aaa", "aaa", "aaa", 5, 6]

Array Flattening

function Flat(arr = []) {
    return arr.reduce((t, v) => t.concat(Array.isArray(v) ? Flat(v) : v), [])
}
const arr = [0, 1, [2, 3], [4, 5, [6, 7]], [8, [9, 10, [11, 12]]]];
Flat(arr); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

Array deduplication

function Uniq(arr = []) {
    return arr.reduce((t, v) => t.includes(v) ? t : [...t, v], []);
}
const arr = [2, 1, 0, 3, 2, 1, 2];
Uniq(arr); // [2, 1, 0, 3]

Array maximum and minimum values

function Max(arr = []) {
    return arr.reduce((t, v) => t > v ? t : v);
}

function Min(arr = []) {
    return arr.reduce((t, v) => t < v ? t : v);
}
const arr = [12, 45, 21, 65, 38, 76, 108, 43];
Max(arr); // 108
Min(arr); // 12

Array members are disassembled independently

function Unzip(arr = []) {
    return arr.reduce(
        (t, v) => (v.forEach((w, i) => t[i].push(w)), t),
        Array.from({ length: Math.max(...arr.map(v => v.length)) }).map(v => [])
    );
}
const arr = [["a", 1, true], ["b", 2, false]];
Unzip(arr); // [["a", "b"], [1, 2], [true, false]]

Array member count

function Count(arr = []) {
    return arr.reduce((t, v) => (t[v] = (t[v] || 0) + 1, t), {});
}
const arr = [0, 1, 1, 2, 2, 2];
Count(arr); // { 0: 1, 1: 2, 2: 3 }

This method is based on the principle of character statistics and word statistics. When entering the parameter, just process the string into an array.

Array member position record

function Position(arr = [], val) {
    return arr.reduce((t, v, i) => (v === val && t.push(i), t), []);
}
const arr = [2, 1, 5, 4, 2, 1, 6, 6, 7];
Position(arr, 2); // [0, 4]

Array member attribute grouping

function Group(arr = [], key) {
    return key ? arr.reduce((t, v) => (!t[v[key]] && (t[v[key]] = []), t[v[key]].push(v), t), {}) : {};
}
const arr = [
    { area: "GZ", name: "YZW", age: 27 },
    { area: "GZ", name: "TYJ", age: 25 },
    { area: "SZ", name: "AAA", age: 23 },
    { area: "FS", name: "BBB", age: 21 },
    { area: "SZ", name: "CCC", age: 19 }
]; // Use area as the grouping basis Group(arr, "area"); // { GZ: Array(2), SZ: Array(2), FS: Array(1) }

Keyword statistics of array members

function Keyword(arr = [], keys = []) {
    return keys.reduce((t, v) => (arr.some(w => w.includes(v)) && t.push(v), t), []);
}
const text = [
    "It's a nice day today, I want to go fishing",
    "I watch TV while doing my homework",
    "Xiao Ming likes Xiao Hong, who is sitting next to him, and Xiao Jun, who is sitting next to him. He is so fickle",
    "There are too many people who like to slack off at work recently. They don't write code properly and are daydreaming."
];
const keyword = ["lazy", "like", "sleep", "fishing", "great", "while", "tomorrow"];
Keyword(text, keyword); // ["like", "slacking off", "really nice", "while"]

String Reversal

function ReverseStr(str = "") {
    return str.split("").reduceRight((t, v) => t + v);
}
const str = "reduce is the best";
ReverseStr(str); // "The most powerful ecuder"

Digital millennials

function ThousandNum(num = 0) {
    const str = (+num).toString().split(".");
    const int = nums => nums.split("").reverse().reduceRight((t, v, i) => t + (i % 3 ? v : `${v},`), "").replace(/^,|,$/g, "");
    const dec = nums => nums.split("").reduce((t, v, i) => t + ((i + 1) % 3 ? v : `${v},`), "").replace(/^,|,$/g, "");
    return str.length > 1 ? `${int(str[0])}.${dec(str[1])}` : int(str[0]);
}
ThousandNum(1234); // "1,234"
ThousandNum(1234.00); // "1,234"
ThousandNum(0.1234); // "0.123,4"
ThousandNum(1234.5678); // "1,234.567,8"

Asynchronous accumulation

async function AsyncTotal(arr = []) {
    return arr.reduce(async(t, v) => {
        const at = await t;
        const todo = await Todo(v);
        at[v] = todo;
        return at;
    }, Promise.resolve({}));
}
const result = await AsyncTotal(); // Need to be used in async surround

Fibonacci Sequence

function Fibonacci(len = 2) {
    const arr = [...new Array(len).keys()];
    return arr.reduce((t, v, i) => (i > 1 && t.push(t[i - 1] + t[i - 2]), t), [0, 1]);
}
Fibonacci(10); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

URL parameter deserialization

function ParseUrlSearch() {
    return location.search.replace(/(^\?)|(&$)/g, "").split("&").reduce((t, v) => {
        const [key, val] = v.split("=");
        t[key] = decodeURIComponent(val);
        return t;
    }, {});
}
// Assume the URL is: https://www.baidu.com?age=25&name=TYJ
ParseUrlSearch(); // { age: "25", name: "TYJ" }

URL parameter serialization

function StringifyUrlSearch(search = {}) {
    return Object.entries(search).reduce(
        (t, v) => `${t}${v[0]}=${encodeURIComponent(v[1])}&`,
        Object.keys(search).length ? "?" : ""
    ).replace(/&$/, "");
}
StringifyUrlSearch({ age: 27, name: "YZW" }); // "?age=27&name=YZW"

Returns the value of the specified key in the object

function GetKeys(obj = {}, keys = []) {
    return Object.keys(obj).reduce((t, v) => (keys.includes(v) && (t[v] = obj[v]), t), {});
}
const target = { a: 1, b: 2, c: 3, d: 4 };
const keyword = ["a", "d"];
GetKeys(target, keyword); // { a: 1, d: 4 }

Array to Object

const people = [
    { area: "GZ", name: "YZW", age: 27 },
    { area: "SZ", name: "TYJ", age: 25 }
];
const map = people.reduce((t, v) => {
    const { name, ...rest } = v;
    t[name] = rest;
    return t;
}, {}); // { YZW: {…}, TYJ: {…} }

Redux Compose function principle

function Compose(...funs) {
    if (funs.length === 0) {
        return arg => arg;
    }
    if (funs.length === 1) {
        return funs[0];
    }
    return funs.reduce((t, v) => (...arg) => t(v(...arg)));
}

Compatibility and performance

It is easy to use, but how about its compatibility? Search on Caniuse, the compatibility is absolutely good and you can use it boldly in any project. Don't be stingy with your imagination and give full play to your reduce compose skills. For functions that often perform some accumulation, reduce is definitely the preferred method.

In addition, some students may ask, what about the performance of reduce? Next, we perform the accumulation operation of 1 to 100,000 on the four methods of for, forEach, map and reduce at the same time to see the execution time of each of the four methods.

// Create an array of length 100000 const list = [...new Array(100000).keys()];

// for
console.time("for");
let result1 = 0;
for (let i = 0; i < list.length; i++) {
    result1 += i + 1;
}
console.log(result1);
console.timeEnd("for");

// forEach
console.time("forEach");
let result2 = 0;
list.forEach(v => (result2 += v + 1));
console.log(result2);
console.timeEnd("forEach");

// map
console.time("map");
let result3 = 0;
list.map(v => (result3 += v + 1, v));
console.log(result3);
console.timeEnd("map");

// reduce
console.time("reduce");
const result4 = list.reduce((t, v) => t + v + 1, 0);
console.log(result4);
console.timeEnd("reduce");
Accumulation Operation Execution time
for 6.719970703125ms
forEach 3.696044921875ms
map 3.554931640625ms
reduce 2.806884765625ms

The above code is executed under Chrome 79 on a MacBook Pro 2019 15-inch with 16G memory and 512G flash memory. There may be differences in the execution of the above code on different machines and in different environments.

I have tested multiple machines and multiple browsers at the same time, and performed the operation more than 10 times in a row. I found that the overall average execution time of reduce is still slightly faster than the other three methods, so you can use it with confidence! This article mainly discusses the usage techniques of reduce. If you have any questions about the compatibility and performance of reduce, you can refer to relevant materials for verification.

Finally, I’ll give you a multiplication table generated by reduce: one times seven equals seven, two times seven equals forty-eight, March 8th is Women’s Day, May 1st is Labor Day, and June 1st is Children’s Day.

Summarize

This concludes this article about 25 advanced uses of JS array reduce that you must know. For more content on advanced uses of JS array reduce, please search previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Detailed explanation of the reduce method of arrays in JavaScript
  • Detailed explanation of JS array Reduce() method and advanced techniques
  • js array method reduce classic usage code sharing
  • Analysis of the principle and usage skills of JS array reduce() method
  • Sharing the magic of Javascript array method reduce
  • Detailed explanation of the function and usage of JS array Reduce method
  • Parsing JavaScript array method reduce
  • Example analysis of the usage of JS array method reduce
  • Detailed explanation of the differences between js array find, some, filter, and reduce
  • JavaScript array reduce common instance methods

<<:  In-depth explanation of MySQL user account management and permission management

>>:  VMware kali virtual machine environment configuration method

Recommend

Linux kernel device driver Linux kernel basic notes summary

1. Linux kernel driver module mechanism Static lo...

CentOS6.9+Mysql5.7.18 source code installation detailed tutorial

CentOS6.9+Mysql5.7.18 source code installation, t...

Detailed steps for adding hosts you need to monitor in zabbix

Add monitoring host Host 192.168.179.104 is added...

A brief discussion on the role of Vue3 defineComponent

Table of contents defineComponent overload functi...

HTML Tutorial: DOCTYPE Abbreviation

When writing HTML code, the first line should be ...

HTML input box optimization to improve user experience and ease of use

In order to improve user experience and ease of us...

Summary of Mathematical Symbols in Unicode

There are many special symbols used in mathematic...

Using CSS3 to achieve progress bar effect and dynamically add percentage

During the project, I started using the js reques...

Introduction to the use of MySQL pt-slave-restart tool

Table of contents When setting up a MySQL master-...

CentOS 7 installation and configuration tutorial under VMware10

If Ubuntu is the most popular Linux operating sys...

How to use the Linux seq command

1. Command Introduction The seq (Sequence) comman...

In-depth explanation of closure in JavaScript

Introduction Closure is a very powerful feature i...

Implementation of Docker packaging image and configuration modification

I have encountered many problems in learning Dock...