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.
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
)
-
callback: callback function (
- 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
)
- total(
- Process
- Use
t
as the initial value of the cumulative result. Ift
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 ofv
tot
, end the loop, and returnt
- Enter the next loop and repeat the above operation until the last element of the array
- ends the traversal and returns the final
t
- Use
##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);
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()对空数组无效
Advanced usage
The above simple chestnut alone is not enough to explain whatreduce 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.
部分示例代码的写法可能有些骚,看得不习惯可自行整理成自己的习惯写法
cumulative multiplication
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
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
replace 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]; // 代替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, []);
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
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), [[]]) : []; }
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]
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); }
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 number statistics
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 }
此方法是字符统计和单词统计的原理,入参时把字符串处理成数组即可
Array member location 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 } ]; // 以地区area作为分组依据 Group(arr, "area"); // { GZ: Array(2), SZ: Array(2), FS: Array(1) }
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), []); }
const text = [ "今天天气真好,我想出去钓鱼", "我一边看电视,一边写作业", "小明喜欢同桌的小红,又喜欢后桌的小君,真TM花心", "最近上班喜欢摸鱼的人实在太多了,代码不好好写,在想入非非" ]; const keyword = ["偷懒", "喜欢", "睡觉", "摸鱼", "真好", "一边", "明天"]; Keyword(text, keyword); // ["喜欢", "摸鱼", "真好", "一边"]
String flip
function ReverseStr(str = "") { return str.split("").reduceRight((t, v) => t + v); }
const str = "reduce最牛逼"; ReverseStr(str); // "逼牛最ecuder"
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]); }
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(); // 需要在async包围下使用
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; }, {}); }
// 假设URL为: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"
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), {}); }
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))); }
兼容和性能
好用是挺好用的,但是兼容性如何呢?在Caniuse上搜索一番,兼容性绝对的好,可大胆在任何项目上使用。不要吝啬你的想象力,尽情发挥reduce
的compose
技能啦。对于时常做一些累计的功能,reduce
绝对是首选方法。
另外,有些同学可能会问,reduce
的性能又如何呢?下面我们通过对for
、forEach
、map
和reduce
四个方法同时做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");
累加操作 | 执行时间 |
---|---|
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
生成的乘法口诀表:一七得七,二七四十八,三八妇女节,五一劳动节,六一儿童节
。
原文地址: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!

JavaScript's application in the real world includes front-end and back-end development. 1) Display front-end applications by building a TODO list application, involving DOM operations and event processing. 2) Build RESTfulAPI through Node.js and Express to demonstrate back-end applications.

The main uses of JavaScript in web development include client interaction, form verification and asynchronous communication. 1) Dynamic content update and user interaction through DOM operations; 2) Client verification is carried out before the user submits data to improve the user experience; 3) Refreshless communication with the server is achieved through AJAX technology.

Understanding how JavaScript engine works internally is important to developers because it helps write more efficient code and understand performance bottlenecks and optimization strategies. 1) The engine's workflow includes three stages: parsing, compiling and execution; 2) During the execution process, the engine will perform dynamic optimization, such as inline cache and hidden classes; 3) Best practices include avoiding global variables, optimizing loops, using const and lets, and avoiding excessive use of closures.

Python is more suitable for beginners, with a smooth learning curve and concise syntax; JavaScript is suitable for front-end development, with a steep learning curve and flexible syntax. 1. Python syntax is intuitive and suitable for data science and back-end development. 2. JavaScript is flexible and widely used in front-end and server-side programming.

Python and JavaScript have their own advantages and disadvantages in terms of community, libraries and resources. 1) The Python community is friendly and suitable for beginners, but the front-end development resources are not as rich as JavaScript. 2) Python is powerful in data science and machine learning libraries, while JavaScript is better in front-end development libraries and frameworks. 3) Both have rich learning resources, but Python is suitable for starting with official documents, while JavaScript is better with MDNWebDocs. The choice should be based on project needs and personal interests.

The shift from C/C to JavaScript requires adapting to dynamic typing, garbage collection and asynchronous programming. 1) C/C is a statically typed language that requires manual memory management, while JavaScript is dynamically typed and garbage collection is automatically processed. 2) C/C needs to be compiled into machine code, while JavaScript is an interpreted language. 3) JavaScript introduces concepts such as closures, prototype chains and Promise, which enhances flexibility and asynchronous programming capabilities.

Different JavaScript engines have different effects when parsing and executing JavaScript code, because the implementation principles and optimization strategies of each engine differ. 1. Lexical analysis: convert source code into lexical unit. 2. Grammar analysis: Generate an abstract syntax tree. 3. Optimization and compilation: Generate machine code through the JIT compiler. 4. Execute: Run the machine code. V8 engine optimizes through instant compilation and hidden class, SpiderMonkey uses a type inference system, resulting in different performance performance on the same code.

JavaScript's applications in the real world include server-side programming, mobile application development and Internet of Things control: 1. Server-side programming is realized through Node.js, suitable for high concurrent request processing. 2. Mobile application development is carried out through ReactNative and supports cross-platform deployment. 3. Used for IoT device control through Johnny-Five library, suitable for hardware interaction.


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Atom editor mac version download
The most popular open source editor

SublimeText3 Linux new version
SublimeText3 Linux latest version

SublimeText3 Mac version
God-level code editing software (SublimeText3)

SublimeText3 English version
Recommended: Win version, supports code prompts!

SAP NetWeaver Server Adapter for Eclipse
Integrate Eclipse with SAP NetWeaver application server.