Home > Web Front-end > JS Tutorial > 25 advanced uses of array reduce worth knowing

25 advanced uses of array reduce worth knowing

青灯夜游
Release: 2021-07-28 09:59:23
forward
2144 people have browsed it

Reduce, as one of the new regular array methods in ES5, is a powerful method. This article will introduce you to 25 advanced uses of array reduce.

25 advanced uses of array reduce worth knowing

reduce As one of the new regular array methods in ES5, compare forEach, filter and map, seems to be somewhat ignored in actual use, and it is found that people around me rarely use it, resulting in such a powerful method being gradually buried.

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

The following is a brief explanation of the syntax of reduce. For details, please view the relevant instructions of reduce() of MDN.

  • Definition: Execute a custom accumulator for each element in the array, summarizing its results into a single return value
  • Form: array.reduce(( t, v, i, a) => {}, initValue)
  • Parameters
    • callback: callback function (required)
    • initValue: Initial value (optional)
  • Parameters of the callback function
    • total(t): The return value when the accumulator completes the calculation (Required)
    • value(v): Current element (Required)
    • index(i): 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 will be the initial value
    • Start traversing, 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
    • ends the traversal and returns the final t

##reduceThe essence is to apply the accumulator to the array members one by one, taking the last output value as the next input value. Here's a simple chestnut to look at the calculation results of reduce.

const arr = [3, 5, 1, 4, 2];
const a = arr.reduce((t, v) => t + v);
// 等同于
const b = arr.reduce((t, v) => t + v, 0);
Copy after login

25 advanced uses of array reduce worth knowing

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

对空数组调用reduce()和reduceRight()是不会执行其回调函数的,可认为reduce()对空数组无效
Copy after login

Advanced usage

The above simple chestnut alone is not enough to explain what

reduce is. In order to show the charm of reduce, I provide you with 25 scenarios to apply the advanced usage of reduce. Some advanced usage may need to be implemented in combination with other methods, which provides more possibilities for diversification of reduce.

部分示例代码的写法可能有些骚,看得不习惯可自行整理成自己的习惯写法
Copy after login

cumulative multiplication

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

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

weight summation

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
Copy after login

replace reverse

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

Replace map and filter

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

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

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

// 代替map和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, []);
Copy after login

Replace some and every

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

// 代替some:至少一门合格
const isAtLeastOneQualified = scores.reduce((t, v) => t || v.score >= 60, false); // true

// 代替every:全部合格
const isAllQualified = scores.reduce((t, v) => t && v.score >= 60, true); // false
Copy after login

Array split

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), [[]]) : [];
}
Copy after login
const arr = [1, 2, 3, 4, 5];
Chunk(arr, 2); // [[1, 2], [3, 4], [5]]
Copy after login

Array filtering

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

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)
    ];
}
Copy after login
const arr = [0, 1, 2, 3, 4, 5, 6];
Fill(arr, "aaa", 2, 5); // [0, 1, "aaa", "aaa", "aaa", 5, 6]
Copy after login

Array flattening

function Flat(arr = []) {
    return arr.reduce((t, v) => t.concat(Array.isArray(v) ? Flat(v) : v), [])
}
Copy after login
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]
Copy after login

Array deduplication

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

Maximum and minimum values ​​of the array

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

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

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 => [])
    );
}
Copy after login
const arr = [["a", 1, true], ["b", 2, false]];
Unzip(arr); // [["a", "b"], [1, 2], [true, false]]
Copy after login

Array member number statistics

function Count(arr = []) {
    return arr.reduce((t, v) => (t[v] = (t[v] || 0) + 1, t), {});
}
Copy after login
const arr = [0, 1, 1, 2, 2, 2];
Count(arr); // { 0: 1, 1: 2, 2: 3 }
Copy after login
此方法是字符统计和单词统计的原理,入参时把字符串处理成数组即可
Copy after login

Array member location record

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

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), {}) : {};
}
Copy after login
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 }
]; // 以地区area作为分组依据
Group(arr, "area"); // { GZ: Array(2), SZ: Array(2), FS: Array(1) }
Copy after login

Keyword statistics contained in array members

function Keyword(arr = [], keys = []) {
    return keys.reduce((t, v) => (arr.some(w => w.includes(v)) && t.push(v), t), []);
}
Copy after login
const text = [
    "今天天气真好,我想出去钓鱼",
    "我一边看电视,一边写作业",
    "小明喜欢同桌的小红,又喜欢后桌的小君,真TM花心",
    "最近上班喜欢摸鱼的人实在太多了,代码不好好写,在想入非非"
];
const keyword = ["偷懒", "喜欢", "睡觉", "摸鱼", "真好", "一边", "明天"];
Keyword(text, keyword); // ["喜欢", "摸鱼", "真好", "一边"]
Copy after login

String flip

function ReverseStr(str = "") {
    return str.split("").reduceRight((t, v) => t + v);
}
Copy after login
const str = "reduce最牛逼";
ReverseStr(str); // "逼牛最ecuder"
Copy after login

number thousands differentiation

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]);
}
Copy after login
ThousandNum(1234); // "1,234"
ThousandNum(1234.00); // "1,234"
ThousandNum(0.1234); // "0.123,4"
ThousandNum(1234.5678); // "1,234.567,8"
Copy after login

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({}));
}
Copy after login
const result = await AsyncTotal(); // 需要在async包围下使用
Copy after login

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]);
}
Copy after login
Fibonacci(10); // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
Copy after login

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;
    }, {});
}
Copy after login
// 假设URL为:https://www.baidu.com?age=25&name=TYJ
ParseUrlSearch(); // { age: "25", name: "TYJ" }
Copy after login

URL parameter serialization

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

Return the specified key value of the object

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

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: {…} }
Copy after login

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)));
}
Copy after login

兼容和性能

好用是挺好用的,但是兼容性如何呢?在Caniuse上搜索一番,兼容性绝对的好,可大胆在任何项目上使用。不要吝啬你的想象力,尽情发挥reducecompose技能啦。对于时常做一些累计的功能,reduce绝对是首选方法。

25 advanced uses of array reduce worth knowing

25 advanced uses of array reduce worth knowing

另外,有些同学可能会问,reduce的性能又如何呢?下面我们通过对forforEachmapreduce四个方法同时做1~100000的累加操作,看看四个方法各自的执行时间。

// 创建一个长度为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");
Copy after login

累加操作 执行时间
for 6.719970703125ms
forEach 3.696044921875ms
map 3.554931640625ms
reduce 2.806884765625ms

以上代码在MacBook Pro 2019 15寸 16G内存 512G闪存Chrome 79下执行,不同的机器不同的环境下执行以上代码都有可能存在差异。

我已同时测试过多台机器和多个浏览器,连续做了10次以上操作,发现reduce总体的平均执行时间还是会比其他三个方法稍微快一点,所以大家还是放心使用啦!本文更多是探讨reduce的使用技巧,如对reduce的兼容和性能存在疑问,可自行参考相关资料进行验证。

最后,送大家一张reduce生成的乘法口诀表:一七得七,二七四十八,三八妇女节,五一劳动节,六一儿童节

25 advanced uses of array reduce worth knowing

25 advanced uses of array reduce worth knowing

原文地址:https://juejin.cn/post/6844904063729926152

作者:JowayYoung

更多编程相关知识,请访问:编程视频!!

The above is the detailed content of 25 advanced uses of array reduce worth knowing. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:juejin.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template