reduce的妙用之处!的数组方法基本用法
大家好,我是 CUGGZ。
在 JavaScript 中,reduce 是最难理解的数组方法之一,它是一个强大而灵活的高阶函数js 递归遍历嵌套数组,下面就来看看 reduce 的妙用之处!
1. 基本用法
reduce() 是 JavaScript 中一个很有用的数组方法,MDN 对其解释如下:
reduce() 方法对数组中的每个元素按序执行一个 reducer 函数,每一次运行 reducer 会将先前元素的计算结果作为参数传入,最后将其结果汇总为单个返回值。
reduce() 方法的语法如下:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">array.reduce(reducer, initialValue)
</pre>
其中有两个参数:(1)reducer 函数,包含四个参数:
(2)initialValue 可选作为第一次调用 callback 函数时参数 previousValue 的值。若指定了初始值 initialValue,则 currentValue 则将使用数组第一个元素;否则 previousValue 将使用数组第一个元素,而 currentValue 将使用数组第二个元素。
下面是一个使用reduce() 求数组元素之和的例子:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const arr = [0, 1, 2, 3, 4]; const calculateSum = (previousValue, currentValue) => { console.log('previousValue: ', previousValue); console.log('currentValue:', currentValue); return previousValue + currentValue; }; arr.reduce(calculateSum)
</pre>
reducer 会逐个遍历数组元素,每一步都将当前元素的值与上一步的计算结果相加(上一步的计算结果是当前元素之前所有元素的总和),直到没有更多的元素被相加。
这段代码的输出如下:
其执行过程如下:
当我们给reduce()方法一个初始值12时:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">arr.reduce(calculateSum, 12);
</pre>
其执行过程如下:
如果数组为空且未提供初始值,reduce() 方法就会抛出 TypeError:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const reducer = (accumulator, currentValue) => accumulator + currentValue; const result = [].reduce(reducer) console.log(result)
</pre>
输出结果如下:
2. 使用技巧(1)数组求和
reduce()方法最直接的用法就是对数组元素求和:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const total = [34, 12, 143, 13, 76].reduce( (previousValue, currentValue) => previousValue + currentValue, 0 ); console.log(total);
</pre>
其输出结果如下:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">278
</pre>
(2)扁平数组
reduce()方法还可以用来扁平化数组:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const array = [[0, 1], [2, 3], [4, 5], [5, 6]]; const flattenedArray = array.reduce( (previousValue, currentValue) => previousValue.concat(currentValue), [] ); console.log(flattenedArray);
</pre>
输出结果如下:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">[0, 1, 2, 3, 4, 5, 5, 6]
</pre>
如果数组有不止一层嵌套数组,可以递归调用 reduce 函数来扁平化,然后将它们与最终的数组连接起来即可。
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const nestedArray = [[1, [2, 3]], [4, 5], [[6, 7], [8, 9]]]; function flattenArray(nestedArray) { return nestedArray.reduce( (accumulator, currentValue) => accumulator.concat( Array.isArray(currentValue) ? flattenArray(currentValue) : currentValue ), []); } const flattenedArray = flattenArray(nestedArray); console.log(flattenedArray)
</pre>
输出结果如下:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">[1, 2, 3, 4, 5, 6, 7, 8, 9]
</pre>
(3)数组分组
假设有一个国家对象数组,根据国家所在洲对数组中的每个国家进行分组。可以使用 reduce 方法来完成:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">cosnt countries = [ {name: "Germany", continent: "Europe"}, {name: "Brazil", continent: "South America"}, {name: "India", continent: "Asia"}, {name: "France", continent: "Europe"}, {name: "South Korea", continent: "Asia"}, ] const groupedCountries = countries.reduce( (groupedCountries, country) => { if (!groupedCountries[country.continent]){ groupedCountries[country.continent] = [] } groupedCountries[country.continent].push(country) return groupedCountries }, {} ); console.log(groupedCountries)
</pre>
输出结果如下:
(4)使用 reduce() 代替 filter().map()
在 Javascript 中,数组的 filter 方法可以通过回调过滤数组中的元素,map 方法可以通过回调内部传递的逻辑使用旧数组创建一个新数组。有时我们必须同时使用这两种方法,对某些条件过滤的结果创建一个新数组。
可以使用 reduce 方法来完成相同的工作,这样就只需要遍历数组一次。例如,要创建一个大于 30 的数字的平方根数组,使用 filter().map() 可能会这么写:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const numbers = [3, 21, 34, 121, 553, 12, 53, 5, 42, 11]; const newArray = numbers.filter(number => number > 30).map(number => Math.sqrt(number));
</pre>
使用 reduce 实现:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const numbers = [3, 21, 34, 121, 553, 12, 53, 5, 42, 11]; const newArray = numbers.reduce((previousValue, currentValue) => { if (currentValue > 30) { previousValue.push(Math.sqrt(currentValue)) } return previousValue }, []); console.log(newArray);
</pre>
输出结果如下:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;"> [5.830951894845301, 11, 23.515952032609693, 7.280109889280518, 6.48074069840786]
</pre>
(5)统计数组元素出现次数
可以使用reduce来统计数组中每个元素出现的次数:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const colors = ['green', 'red', 'red', 'yellow', 'red', 'yellow', 'green', 'green']; const colorMap = colors.reduce((previousValue, currentValue) => { previousValue[currentValue] >= 1 ? previousValue[currentValue]++ : previousValue[currentValue] = 1; return previousValue; }, {} ); console.log(colorMap);
</pre>
输出结果如下:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">{green: 3, red: 3, yellow: 2}
</pre>
(6)串行执行异步函数
有一组需要串行执行的异步函数,可以使用reduce()来调用执行:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const functions = [ async function() { return 1; }, async function() { return 2; }, async function() { return 3; } ]; const res = await functions.reduce((promise, fn) => promise.then(fn), Promise.resolve()); console.log(res); // 输出结果:3
</pre>
这里的 res 就相当于执行了:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">Promise.resolve().then(fn1).then(fn2).then(fn3);
</pre>
(7)创建管道
假设有一组简单的数学函数,这些函数允许我们增加、减少、加倍和减半:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">function increment(input) { return input + 1;} function decrement(input) { return input — 1; } function double(input) { return input * 2; } function halve(input) { return input / 2; }
</pre>
如果想对一个值进行多次上述操作,就可以使用reduce()。管道是用于将某些初始值转换为最终值的函数列表的术语。我们只需将执行过程中每一步用到函数写在管道数组中即可。
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const pipeline = [increment, double, decrement]; const result = pipeline.reduce((total, func) => { return func(total); }, 5); console.log(result) // 输出结果:11
</pre>
(8)反转字符串
可以使用reduce()实现字符串的反转:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const str = 'hello world'; [...str].reduce((a,v) => v + a); // 输出结果:'dlrow olleh'
</pre>
(9)数组去重
有一个包含重复项的数组,可以使用 reduce() 来对数组进行去重:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">const arr = ["", "", "", ""]; const dedupe = (acc, currentValue) => { if (!acc.includes(currentValue)) { acc.push(currentValue); } return acc; }; const dedupedArr = arr.reduce(dedupe, []); console.log(dedupedArr); // ["", ""];
</pre>
其执行过程如下:
当 reduce 方法遍历数组时,回调函数将应用于数组中的每一项。它会检查累加器中是否缺少当前值,如果是,则将当前值 push 到累加器中。
注:此示例仅用于说明 reduce 方法的工作原理js 递归遍历嵌套数组,在实践中,通常会选择使用 Set 对数组进行去重,这是一种性能更高的方法:
<pre data-tool="mdnice编辑器" style="margin-top: 10px;margin-bottom: 10px;border-radius: 5px;box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">dedupedArr = [...new Set(array)];
</pre>
往期推荐:
发表评论
热门文章
Spimes主题专为博客、自媒体、资讯类的网站设计....
一款个人简历主题,可以简单搭建一下,具体也比较简单....
仿制主题,Typecho博客主题,昼夜双版设计,可....
用于作品展示、资源下载,行业垂直性网站、个人博客,....
54447454
10月31日
[已回复]
能重复在发一下吗,无法下载了