【JS】详解reduce()方法及其奇技淫巧、性能

历史小剧场

或许到人生的最后一刻,他都不知道自己为什么会死,他永远也不会知道,在这个世界上,有着许多或明或暗的规则,必须适应,必须放弃原则,背离良知,与光同尘,否则你有多么伟大的抱负、多么光辉的理想,都终将被湮灭。
袁崇焕是不知道与光同尘的,由始至终,他都是一个不上道的人,他有才能、有抱负、有个性,施展自己的才能,实现自己的抱负,彰显自己的个性,如此而已。----《明朝那些事儿》

概念及参数

  • 定义:对数组中的每个元素执行一个自定义的累加器,
  • 参数:第一个:回调函数;第二个:初始值(可选)
  • 回调函数参数(4个):
    • acc: 累计器完成计算的返回值(必选)
    • val: 当前迭代到的元素(必选)
    • index: 当前迭代到的元素在数组中的位置索引(可选)
    • arr: 原数组对象

奇技淫巧

1. 累加累乘
const accumulation = (...vals) => vals.reduce((acc, val) => acc + val, 0);
const multiplication = (...vals) => vals.reduce((acc, val) => acc * val, 1);

console.log(accumulation(1, 2, 3, 4, 5)); // 15
console.log(multiplication(1, 2, 3, 4, 5)); // 120
2. 权重求和
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((acc, val) => acc + val.score * val.weight, 0);
console.log(result); // 90.5
3. 代替reverse()
const reverse = (arr = []) => arr.reduce((acc, val) => [val].concat(acc), []);
console.log(reverse([1, 2, 3, 4, 5])); // [5, 4, 3, 2, 1]
4. 代替map()和filter()
const arr = [0, 1, 2, 3];

console.log(arr.map(val => val * 2)) // [ 0, 2, 4, 6 ]
console.log(arr.reduce((acc, val) => [...acc, val * 2], [])) // [ 0, 2, 4, 6 ]

console.log(arr.filter(val => val > 1)) // [ 2, 3 ]
console.log(arr.reduce((acc, val) => acc.concat(val > 1 ? val : []), [])) // [ 2, 3 ]

console.log(arr.filter(val => val > 1).map(val => val * 2)) // [ 4, 6 ]
console.log(arr.reduce((acc, val) => acc.concat(val > 1 ? val * 2 : []), [])) // [ 4, 6 ]
5. 代替some和every
const scoreList = [
    { subject: 'chinese', score: 45 },
    { subject: 'Math', score: 90 },
    { subject: 'English', score: 60 }
]
// 代替some
console.log(scoreList.reduce((acc, val) => acc || val.score >= 60, false)) // true
// 代替every
console.log(scoreList.reduce((acc, val) => acc && val.score >= 60, false)) // false
6. 数组分割
const chunk = (arr = [], size = 1) => arr.length ?
    arr.reduce((acc, val) => (
        Object.is(acc[acc.length - 1].length, size) ?
        acc.push([val]) : acc[acc.length - 1].push(val), acc
    ), [[]])
    : []

console.log(chunk([1, 2, 3, 4, 5], 1))  // [ [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ] ]
console.log(chunk([1, 2, 3, 4, 5], 2))  // [ [ 1, 2 ], [ 3, 4 ], [ 5 ] ]
console.log(chunk([1, 2, 3, 4, 5], 3))  // [ [ 1, 2, 3 ], [ 4, 5 ] ]
console.log(chunk([1, 2, 3, 4, 5], 4))  // [ [ 1, 2, 3, 4 ], [ 5 ] ]
console.log(chunk([1, 2, 3, 4, 5], 5))  // [ [ 1, 2, 3, 4, 5 ] ]
console.log(chunk([1, 2, 3, 4, 5], 6))  // [ [ 1, 2, 3, 4, 5 ] ]
7. 数组过滤
const difference = (arr = [], oarr = []) => arr.reduce((acc, val) => (!oarr.includes(val) && acc.push(val), acc), [])
console.log(difference([1, 2, 3, 4, 5], [2, 3, 6]))  // [ 1, 4, 5 ]
8. 数组填充
const fill = (arr = [], data = '', start = 0, count = 0) => {
    const end = arr.length - 1;
    if (start < 0 || start > end) return arr;
    return [
        ...arr.slice(0, start),
        ...arr.slice(start, start + count).reduce((acc, val) => (acc.push(data || val), acc), []),
        ...arr.slice(start, end + count)
    ]
}
const fillArr = [0, 1, 2, 3, 4, 5, 6];
console.log(fill(fillArr, 'aaa', 2, 3)) // [0,1,'aaa','aaa', 'aaa',2,3,4,5,6]
9. 数组扁平
console.log("------------------------------")
const flat = (arr = []) => arr.reduce((acc, val) => {
    return acc.concat(Array.isArray(val) ? flat(val) : val)
}, [])
const flatArr = [0, 1, [2, 3], [4, 5, [6, 7]], [8, [9, 10, [11, 12]]]];
console.log(flat(flatArr)) 
10. 数组去重
const unique = (arr = []) => arr.reduce((acc, val) => !acc.includes(val) ? [...acc, val] : acc , [])
console.log(unique([2, 1, 0, 3, 2, 1, 2])) // [ 2, 1, 0, 3 ]
11. 数组最大最小值
const max = (arr = []) => arr.reduce((acc, val) => Math.max(acc, val))
console.log(max([12, 45, 21, 65, 38, 76, 108, 43])) // 108
const min = (arr = []) => arr.reduce((acc, val) => Math.min(acc, val))
console.log(min([12, 45, 21, 65, 38, 76, 108, 43])) // 12
12. 数组成员独立拆解
const unzip = (arr = []) => arr.reduce(
    (acc, val) => (val.forEach((subVal, index) => acc[index].push(subVal)), acc),
    Array.from({ length: Math.max(...arr.map(val => val.length)) }).map(() => [])
)
const zipArr = [["a", 1, true], ["b", 2, false]];
console.log(unzip(zipArr)) // [ [ 'a', 'b' ], [ 1, 2 ], [ true, false ] ]
13. 数组成员个数统计
const count = (arr = []) => arr.reduce((acc, val) => (acc[val] = (acc[val] || 0) + 1, acc), {})
console.log(count([1, 2, 3, 2, 1, 2])) // { '1': 2, '2': 3, '3': 1 }
14. 数组成员位置记录
const position = (arr = [], target) => arr.reduce((acc, val, i) => (Object.is(val, target) && acc.push(i), acc), [])
console.log(position([2, 1, 3, 2, 1, 2], 2)) // [ 0, 3, 5 ]
15. 数组成员特性分组
const group = (arr = [], key) => key ?
    arr.reduce((acc, val) => (!acc[val[key]] && (acc[val[key]] = []), acc[val[key]].push(val), acc), {})
    : {}
const groupArr = [
    { area: "GZ", name: "YZW", age: 22 },
    { area: "GZ", name: "TYJ", age: 20 },
    { area: "SZ", name: "AAA", age: 22 },
    { area: "FS", name: "BBB", age: 23 },
    { area: "SZ", name: "CCC", age: 20 }
]; 
console.log(group(groupArr, "area")) 
// {
// GZ: [
//     { area: 'GZ', name: 'YZW', age: 22 },
//     { area: 'GZ', name: 'TYJ', age: 20 }
// ],
// SZ: [
//     { area: 'SZ', name: 'AAA', age: 22 },
//     { area: 'SZ', name: 'CCC', age: 20 }
// ],
// FS: [ { area: 'FS', name: 'BBB', age: 23 } ]
// }
console.log("------------------------------")
console.log(group(groupArr, "age"))
16. 字符串反转
const reverseStr = (str = '') => str.split('').reduceRight((acc, val) => acc + val)
console.log(reverseStr('reduce真强')) // 强真ecuder
17. 斐波那契数列
const fibonacci = (len = 0) => {
    const arr = [...Array(len).keys()]
    return arr.reduce((acc, val, index) => (index > 1 && acc.push(acc[index - 1] + acc[index - 2]), acc), [0, 1])
}

console.log(fibonacci(10)) // [0, 1,  1,  2,  3, 5, 8, 13, 21, 34]
18. URL参数反序列化
const parseUrlParam = (url = '') => {
    const params = url.split('?')[1]
    return params ? params.split('&').reduce((acc, val) => {
        const [key, value] = val.split('=')
        acc[key] = decodeURIComponent(value)
        return acc
    }, {}) : {}
}
console.log(parseUrlParam('https://www.baidu.com/s?wd=reduce&ie=utf-8')) // { wd: 'reduce', ie: 'utf-8' }
19. URL参数序列化
const stringifyUrlParam = (obj = {}) => Object.entries(obj).reduce((acc, val) => {
    const [key, value] = val
    return `${acc}${key}=${encodeURIComponent(value)}&`
}, obj.length === 0 ?  "" : "?").slice(0, -1)
console.log(stringifyUrlParam({ wd: 'reduce', ie: 'utf-8' })) // 'wd=reduce&ie=utf-8'
20. 返回对象指定键值
const getKeys = (obj = {}, keys = []) => keys.reduce((acc, val) => (acc[val] = obj[val], acc), {})
console.log(getKeys({ a: 1, b: 2, c: 3 }, ['a', 'c'])) // { a: 1, c: 3 }
21. 数组转对象
const people = [
    { area: "GZ", name: "YZW", age: 27 },
    { area: "SZ", name: "TYJ", age: 25 }
];
const peopleObj = people.reduce((acc, val, index, arr) => {
    const { name, ...rest } = val
    acc[name] = rest
    return acc
}, {})
console.log(peopleObj) // { YZW: { area: 'GZ', name: 'YZW', age: 27 }, TYJ: { area: 'SZ', name: 'TYJ', age: 25 } }
22. 功能性函数管道(函数组合)
const double = val => val * 2;
const add = val => val + 1;
const pipe = (...funcs) => val => funcs.reduce((acc, func) => func(acc), val);

// ===
// const pipe = (...funcs) => {
//     return (val) => {
//         return reduce(funcs, (acc, func) => func(acc), val);
//     }
// }

console.log(pipe(double, add)(5)); // 5 * 2 + 1 = 11

性能测试

1. 数据量较小:1000条
const list = [...Array(1000).keys()];

// map
console.time("map")
let sum3 = 0;
list.map(val => (sum3 += val, val))
console.log(sum3);
console.timeEnd("map")


// for
console.time('for');
let sum1 = 0;
for (let i = 0, len = list.length; i < len; i++) {
    sum1 += list[i];
}
console.log(sum1);
console.timeEnd('for');

// forEach
console.time('forEach');
let sum2 = 0;
list.forEach(val => {
    sum2 += val;
});
console.log(sum2);
console.timeEnd('forEach');

// reduce
console.time("reduce")
let sum4 = list.reduce((acc, val) => (acc += val, acc), 0)
console.log(sum4);
console.timeEnd("reduce")

运行结果

在这里插入图片描述
在数据量较小的情况下,reduce()方法性能较好;for循环方法性能较差(注意:在不同机器上会有差异)

2. 数据量较大:10000000

在这里插入图片描述
在数据量较小的情况下,for循环方法性能较好;map()方法性能较差(注意:在不同机器上会有差异)

注意:这里的for循环获取数组长度只获取了一次

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/683578.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

make_ext4fs:not found

报错信息&#xff1a; 解决&#xff1a; sudo apt-get install android-tools-fsutils sudo apt-get install android-sdk-libsparse-utils sudo apt-get install android-sdk-ext4-utils

代码随想录训练营Day29

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、递增子序列二、全排列三、全排列2 前言 今天是跟着代码随想录刷题的第29天&#xff0c;今天主要学了以下几个内容&#xff1a;491.递增子序列、46.全排列、…

python中实现队列功能

【小白从小学Python、C、Java】 【考研初试复试毕业设计】 【Python基础AI数据分析】 python中实现队列功能 选择题 以下代码最后一次输出的结果是&#xff1f; from collections import deque queue deque() queue.append(1) queue.append(2) queue.append(3) print(【显示】…

惊呆了!六西格玛培训竟然这么强大!——张驰咨询

六西格玛&#xff0c;这个在业界久负盛名的管理理念&#xff0c;它的魅力太强大了。曾听闻它能帮助企业和个人提升竞争力&#xff0c;但当真正走进这个培训体系时&#xff0c;会发现它的影响力远超你的想象。 在六西格玛的指导下&#xff0c;企业实现了显著的转变。之前那些看…

微软云计算[1]之云计算平台、云操作系统Windows Azure

微软云计算平台 微软云计算平台微软的云计算技术Windows Azure组成 微软云操作系统Windows AzureWindows Azure概述Windows Azure计算服务Windows Azure存储服务全局命名空间体系架构存储域的层次结构双复制引擎文件流层分区层 Windows Azure ConnectWindows Azure CDNFabric控…

第二证券股市资讯:全球第二!英伟达市值再超苹果

昨夜&#xff0c;英伟达股价再度大涨。‍‍‍ 当地时间6月5日周三&#xff0c;美股三大股指全线收涨。到收盘&#xff0c;道指涨0.25%&#xff0c;纳指涨1.96%&#xff0c;标普500指数涨1.18%。 经济数据方面&#xff0c;美国5月ADP新增工作人数15.2万人&#xff0c;低于预期…

python书上的动物是啥

Python的创始人为Guido van Rossum。1989年圣诞节期间&#xff0c;在阿姆斯特丹&#xff0c;Guido为了打发圣诞节的无趣&#xff0c;决心开发一个新的脚本解释程序&#xff0c;做为ABC语言的一种继承。之所以选中Python作为程序的名字&#xff0c;是因为他是一个叫Monty Python…

【Python报错】AttributeError: ‘NoneType‘ object has no attribute ‘xxx‘

成功解决“AttributeError: ‘NoneType’ object has no attribute ‘xxx’”错误的全面指南 一、引言 在Python编程中&#xff0c;AttributeError是一种常见的异常类型&#xff0c;它通常表示尝试访问对象没有的属性或方法。而当我们看到错误消息“AttributeError: ‘NoneTyp…

基于springboot实现餐饮管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现餐饮管理系统演示 摘要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对信息管理混乱&#xff0c;出错率…

基于springboot实现民族婚纱预定系统项目【项目源码+论文说明】

基于springboot实现民族婚纱预定系统的设计演示 摘要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本民族婚纱预定系统就是在这样的大环境下诞生&#xff0c;其可…

3. 使用tcpdump抓取rdma数据包

系列文章 第1章 多机多卡运行nccl-tests 和channel获取第2章 多机多卡nccl-tests 对比分析第3章 使用tcpdump抓取rdma数据包 目录 系列文章一、准备工作1. 源码编译tcpdump2. 安装wireshark 二、Tcpdump抓包三、Wireshark分析 一、准备工作 1. 源码编译tcpdump 使用 tcpdump…

一、【源码】创建简单的映射器代理工厂

源码地址&#xff1a;https://github.com/mybatis/mybatis-3/ 仓库地址&#xff1a;https://gitcode.net/qq_42665745/mybatis/-/tree/01-xxxDao-proxy 创建简单的映射器代理工厂 执行xxxDao.method()时都做了些什么&#xff1f; 原理是&#xff1a;首先定义Dao接口&#xff…

一周学会Django5 Python Web开发 - Django5内置Auth认证系统-用户登录实现

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计57条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

企业购买一套ABAQUS需要多少钱?ABAQUS价格解析

在高性能仿真分析领域&#xff0c;ABAQUS软件凭借其强大的非线性分析能力、精确的求解精度以及广泛的应用范围&#xff0c;成为众多企业和研究机构的首选工具。然而&#xff0c;对于想要采购ABAQUS的企业来说&#xff0c;了解其价格体系是做出投资决策前的关键一步。亿达四方&a…

增值税发票OCR识别功能介绍

OCR增值税发票识别功能介绍如下&#xff1a; 一、技术原理 OCR增值税发票识别系统基于光学字符识别&#xff08;OCR&#xff09;技术和人工智能的支持&#xff0c;将传统纸质发票的信息自动转换为计算机可以读取的数字信息。具体技术流程包括&#xff1a; 图像预处理&#x…

Spring Boot项目中,如何在yml配置文件中读取maven pom.xml文件中的properties标签下的属性值

一、前言 在最近的项目开发过程中&#xff0c;有一个需求&#xff0c;需要在Spring Boot项目的yml配置文件中读取到mave的 pom.xml文件中的properties标签下的属性值&#xff0c;这个要怎么实现呢&#xff1f; 二、技术实践 pom.xml文件中增加测试属性 <properties><…

Vue06-el与data的两种写法

一、el属性 用来指示vue编译器从什么地方开始解析 vue的语法&#xff0c;可以说是一个占位符。 1-1、写法一 1-2、写法二 当不使用el属性的时候&#xff1a; 两种写法都可以。 v.$mount(#root);写法的好处&#xff1a;比较灵活&#xff1a; 二、data的两种写法 2-1、对象式…

基于web的垃圾分类回收系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;用户管理&#xff0c;公告管理&#xff0c;运输管理&#xff0c;基础数据管理 用户账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;运输管理&#xff0c;公告…

麒麟桌面操作系统KYLINOS 2403安装部署

原文链接&#xff1a;麒麟桌面操作系统KYLINOS 2403安装部署 Hello&#xff0c;大家好啊&#xff01;今天给大家带来一篇关于麒麟桌面操作系统2403的安装部署文章。麒麟操作系统是中国自主研发的Linux发行版&#xff0c;以其安全性和稳定性受到广泛关注和使用。本文将详细介绍如…

ChatGPT基本原理详细解说

ChatGPT基本原理详细解说 引言 在人工智能领域&#xff0c;自然语言处理&#xff08;NLP&#xff09;一直是研究的热点之一。随着技术的发展&#xff0c;我们见证了从简单的聊天机器人到复杂的语言模型的演变。其中&#xff0c;ChatGPT作为一项突破性技术&#xff0c;以其强大…