js数组分组,javascript实现数组的按属性分组

在JavaScript中,有多种方法可以对数组按属性进行分组。以下是至少6种常见的方法:

6种方法的使用场景和优缺点的简要描述:

  1. 使用reduce()方法:

    • 使用场景:适用于需要对数组进行聚合操作的情况,可以自定义聚合逻辑。
    • 优点:灵活性高,可以自定义聚合逻辑;可以同时对多个属性进行分组。
    • 缺点:代码相对复杂,需要熟悉reduce()方法的使用。
  2. 使用forEach()方法:

    • 使用场景:适用于简单的分组需求,不需要自定义聚合逻辑。
    • 优点:简单易懂,代码量较少。
    • 缺点:无法同时对多个属性进行分组;不支持链式操作。
  3. 使用map()方法和Object.create(null):

    • 使用场景:适用于需要创建一个纯净的空对象作为分组结果的情况。
    • 优点:可以创建一个没有原型链的空对象,避免可能的属性冲突。
    • 缺点:相对于使用普通对象,性能稍差。
  4. 使用Map对象:

    • 使用场景:适用于需要对分组结果进行进一步操作的情况,如遍历、删除、更新等。
    • 优点:支持对分组结果进行灵活的操作;可以同时对多个属性进行分组。
    • 缺点:相对于普通对象,Map对象的性能稍差。
  5. 使用lodash库的groupBy()方法:

    • 使用场景:适用于使用lodash库的项目,或者需要使用其他lodash库的功能。
    • 优点:简单易用,代码量少;lodash库提供了丰富的其他功能。
    • 缺点:引入了额外的库,增加了项目的依赖。
  6. 使用ES6的Map和箭头函数:

    • 使用场景:适用于需要使用ES6的特性,或者需要对分组结果进行进一步操作的情况。
    • 优点:支持对分组结果进行灵活的操作;可以同时对多个属性进行分组;使用了ES6的特性。
    • 缺点:相对于普通对象,Map对象的性能稍差。

根据具体的需求和项目环境,选择适合的方法可以提高代码的可读性和性能。对于简单的分组需求,可以选择forEach()方法或lodash库的groupBy()方法;对于复杂的分组需求,可以选择reduce()方法、Map对象或ES6的Map和箭头函数。

  1. 使用reduce()方法封装的方法:

这种方法使用reduce()方法来对数组进行迭代,并根据指定的属性值将元素分组。它使用一个空对象作为初始值,然后在迭代过程中,根据属性值将元素添加到相应的分组中。

首先创建一个空对象,用于存储分组结果。
使用for循环遍历数组中的每个元素。
在每次迭代中,使用if语句检查当前元素的属性值是否已经存在于分组对象中。
如果属性值不存在,就创建一个新的属性,并将当前元素添加到该属性对应的数组中。
如果属性值已经存在,就将当前元素添加到该属性对应的数组中。
最后返回分组对象。

使用示例:

const arr = [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Charlie', age: 20, gender: 'male' },{ name: 'David', age: 30, gender: 'male' },{ name: 'Eve', age: 25, gender: 'female' }
];const result = groupByReduce(arr, 'age');
console.log(result);

输出结果:

{'20': [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Charlie', age: 20, gender: 'male' }],'25': [{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Eve', age: 25, gender: 'female' }],'30': [{ name: 'David', age: 30, gender: 'male' }]
}
  1. 使用forEach()方法封装的方法:

这种方法使用forEach()方法对数组进行迭代,并根据指定的属性值将元素分组。它使用一个空对象作为初始值,然后在迭代过程中,根据属性值将元素添加到相应的分组中。

使用reduce方法对数组进行迭代,并传入一个初始值为空对象。
在每次迭代中,使用初始值作为累加器,并根据当前元素的属性值,将元素添加到相应的属性数组中。
最后返回累加器,即分组结果。

使用示例:

const arr = [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Charlie', age: 20, gender: 'male' },{ name: 'David', age: 30, gender: 'male' },{ name: 'Eve', age: 25, gender: 'female' }
];const result = groupByForEach(arr, 'gender');
console.log(result);

输出结果:

{female: [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Eve', age: 25, gender: 'female' }],male: [{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Charlie', age: 20, gender: 'male' },{ name: 'David', age: 30, gender: 'male' }]
}
  1. 使用map()方法和Object.create(null)封装的方法:

这种方法使用map()方法对数组进行迭代,并根据指定的属性值将元素分组。它使用Object.create(null)创建一个没有原型的空对象作为初始值,然后在迭代过程中,根据属性值将元素添加到相应的分组中。

创建一个空的Map对象,用于存储分组结果。
使用forEach方法对数组进行迭代。
在每次迭代中,根据当前元素的属性值,使用Map对象的get方法获取对应的属性数组。
如果属性数组不存在,就创建一个新的属性数组,并将当前元素添加到该数组中。
如果属性数组已经存在,就将当前元素添加到该数组中。
最后将分组结果转换为普通对象,并返回。

使用示例:

const arr = [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Charlie', age: 20, gender: 'male' },{ name: 'David', age: 30, gender: 'male' },{ name: 'Eve', age: 25, gender: 'female' }
];const result = groupByMap(arr, 'age');
console.log(result);

输出结果:

{'20': [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Charlie', age: 20, gender: 'male' }],'25': [{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Eve', age: 25, gender: 'female' }],'30': [{ name: 'David', age: 30, gender: 'male' }]
}
  1. 使用Map对象封装的方法:

这种方法使用Map对象来存储分组结果。它使用forEach()方法对数组进行迭代,并根据指定的属性值将元素分组。在迭代过程中,根据属性值将元素添加到相应的分组中,并使用Map对象的set()方法来保存分组结果。

创建一个空的Map对象,用于存储分组结果。
使用forEach方法对数组进行迭代。
在每次迭代中,使用箭头函数来根据当前元素的属性值,将元素添加到相应的属性数组中。
最后将分组结果转换为普通对象,并返回。
使用示例:

const arr = [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Charlie', age: 20, gender: 'male' },{ name: 'David', age: 30, gender: 'male' },{ name: 'Eve', age: 25, gender: 'female' }
];const result = groupByMapObj(arr, 'gender');
console.log(result);

输出结果:

{female: [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Eve', age: 25, gender: 'female' }],male: [{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Charlie', age: 20, gender: 'male' },{ name: 'David', age: 30, gender: 'male' }]
}
  1. 使用lodash库的groupBy()方法封装的方法:

这种方法使用lodash库的groupBy()方法来实现分组。它接受一个数组和一个属性名作为参数,并返回一个对象,其中键是属性值,值是具有相同属性值的元素数组。
使用lodash库的groupBy方法,传入数组和属性名作为参数。
groupBy方法会根据属性值将数组元素分组,并返回一个对象,其中键是属性值,值是具有相同属性值的元素数组。
返回分组结果

使用示例:

const arr = [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Charlie', age: 20, gender: 'male' },{ name: 'David', age: 30, gender: 'male' },{ name: 'Eve', age: 25, gender: 'female' }
];const result = groupByLodash(arr, 'age');
console.log(result);

输出结果:

{'20': [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Charlie', age: 20, gender: 'male' }],'25': [{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Eve', age: 25, gender: 'female' }],'30': [{ name: 'David', age: 30, gender: 'male' }]
}
  1. 使用ES6的Map和箭头函数封装的方法:

这种方法使用ES6的Map对象来存储分组结果。它使用forEach()方法对数组进行迭代,并根据指定的属性值将元素分组。在迭代过程中,根据属性值将元素添加到相应的分组中,并使用Map对象的set()方法来保存分组结果。
创建一个空的Map对象,用于存储分组结果。
使用forEach方法对数组进行迭代。
在每次迭代中,使用箭头函数来根据当前元素的属性值,将元素添加到相应的属性数组中。
最后将分组结果转换为普通对象,并返回。

使用示例:

const arr = [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Charlie', age: 20, gender: 'male' },{ name: 'David', age: 30, gender: 'male' },{ name: 'Eve', age: 25, gender: 'female' }
];const result = groupByMapArrow(arr, 'gender');
console.log(result);

输出结果:

{female: [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Eve', age: 25, gender: 'female' }],male: [{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Charlie', age: 20, gender: 'male' },{ name: 'David', age: 30, gender: 'male' }]
}

以上是六种不同的方法的详细说明和使用示例。根据需求和个人喜好,可以选择适合的方法来进行分组操作。

试着封装起来

以下是将这6种方法封装

function groupBy(arr, prop, method) {switch (method) {case 'reduce':return arr.reduce((result, item) => {const key = item[prop];if (!result[key]) {result[key] = [];}result[key].push(item);return result;}, {});case 'forEach':const grouped = {};arr.forEach(item => {const key = item[prop];if (!grouped[key]) {grouped[key] = [];}grouped[key].push(item);});return grouped;case 'map':const grouped = Object.create(null);arr.map(item => {const key = item[prop];if (!grouped[key]) {grouped[key] = [];}grouped[key].push(item);});return grouped;case 'mapObj':const grouped = new Map();arr.forEach(item => {const key = item[prop];const group = grouped.get(key) || [];group.push(item);grouped.set(key, group);});return Object.fromEntries(grouped);case 'lodash':const _ = require('lodash');return _.groupBy(arr, prop);case 'mapArrow':const grouped = new Map();arr.forEach(item => {const key = item[prop];const group = grouped.get(key) || [];group.push(item);grouped.set(key, group);});return Object.fromEntries(grouped);default:return {};}
}

使用示例:

const arr = [{ name: 'Alice', age: 20, gender: 'female' },{ name: 'Bob', age: 25, gender: 'male' },{ name: 'Charlie', age: 20, gender: 'male' },{ name: 'David', age: 30, gender: 'male' },{ name: 'Eve', age: 25, gender: 'female' }
];console.log(groupBy(arr, 'age', 'reduce'));
console.log(groupBy(arr, 'gender', 'forEach'));
console.log(groupBy(arr, 'age', 'map'));
console.log(groupBy(arr, 'gender', 'mapObj'));
console.log(groupBy(arr, 'age', 'lodash'));
console.log(groupBy(arr, 'gender', 'mapArrow'));

封装后,可以根据传入的方法名调用相应的分组方法,方便调用和切换不同的分组方法。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 命令大全(下)

Linux 命令大全(上) 本文目录 6. 网络通讯 常用命令6.1 ssh 命令 – 安全的远程连接服务器6.1.1 含义6.1.2 语法格式6.1.3 常用参数6.1.4 参考示例 6.2 netstat 命令 – 显示网络状态6.2.1 含义6.2.2 语法格式6.2.3 常用参数6.2.4 参考示例 6.3 dhclient…

Postgresql的一个bug_涉及归档和pg_wal

故障描述: 服务器ocmpgdbprod1,是流复制主节点,它的从节点是ocmpgdbprod2,两个节点的Postgresql数据库版本都是PostgreSQL 11.6,主节点ocmpgdbprod1配置了pg_wal归档,从节点ocmpgdbprod2没有配置pg_wal归档…

DVWA XSS

反射型 low 查看源代码&#xff0c;没有任何过滤 构造 medium 这里是过滤了 high 这里把双写和大小写和JavaScript都过滤了,用事件来绕过<img src0 οnerrοralert(“xss”)> impossible 这里使用htmlspecialchars进行实体转换并且输出的结果还不能使用事件来…

IOS打包上架AppStore被驳回信息记录

1&#xff1a;错误码5.2.1错误信息如下 Your app includes content or features from 公司名, or is marketed to control external hardware from 公司名, without the necessary authorization. The inclusion of third-party content within your app, whether retrieved fr…

前端面试中Vue的有经典面试题一

1. 谈谈你对MVVM开发模式的理解 MVVM分为Model、View、ViewModel三者。 Model&#xff1a;代表数据模型&#xff0c;数据和业务逻辑都在Model层中定义&#xff1b; View&#xff1a;代表UI视图&#xff0c;负责数据的展示&#xff1b; ViewModel&#xff1a;负责监听Model中…

Android Event事件分发(新版本)

之前写过一个方案&#xff08;添加链接描述&#xff09;&#xff0c;突然觉得很麻烦&#xff0c;于是有了新的方案&#xff1a; 首先先说要解决的问题&#xff1a; 当父布局能滑动&#xff0c;子View也能滑动&#xff0c;就会出现滑动冲突 解决思路&#xff1a;我们按下子Vie…

视觉化洞察:为什么我们需要数据可视化?

为什么我们需要数据可视化&#xff1f;这个问题在信息时代变得愈发重要。数据&#xff0c;如今已成为生活的一部分&#xff0c;我们每天都在产生大量的数据&#xff0c;从社交媒体到购物记录&#xff0c;从健康数据到工作表现&#xff0c;数据无处不在。然而&#xff0c;数据本…

抖音短视频账号矩阵seo分发系统--开发源代

1.抖音矩阵号/抖音短视频SEO矩阵系统开发及开发者思路分享: 短视频获客系统开发原型支持短视频智能批量剪辑、短视频多账号管理定时发布&#xff0c;短视频排名查询及优化&#xff0c;智能客服私信回复等&#xff0c;那么短视频seo系统开发时需要开发哪些功能呢&#xff1f;今天…

SciencePlots 基本语法及特点

文章目录 简介安装 LaTeXSciencePlots 绘图示例 简介 用户有时需要根据期刊的配图绘制要求进行诸如字体、刻度轴、轴脊、图例等图层属性的定制化修改&#xff0c;耗时的同时也会容易导致用户忽略一些图层细节要求。 SciencePlots 作为一个专门用于科研论文绘图的第三方拓展工…

Revit SDK 介绍:DistanceToPanels 根据距离设置参数

前言 这个例子展示如何计算距离&#xff0c;并将距离的值设置为参数。 内容 选中球形&#xff0c;运行程序&#xff0c;会设置控制高度的参数&#xff0c;距离越远参数值越大。效果如下所示&#xff1a; 核心逻辑&#xff1a; 得到选中物体的位置遍历分割表面内部的 Panel…

Unity AssetBundle(1):Assets打包和依赖(Dependencies)

对Unity5.x后的AssetBundle依赖机制有了一点理解&#xff0c;创建了一个项目验证 github:GeWenL / AssetBundlePro AbScene.unity 资源有哪些&#xff1f; Some common types of Asset assetbundle打包命令是 BuildPipeline.BuildAssetBundles ,格式有&#xff1a; 引用&…

Java工具类记录

HTML转word 相关依赖 <dependency><groupId>org.apache.poi</groupId><artifactId>poi</artifactId><version>4.1.2</version></dependency>import org.apache.poi.poifs.filesystem.DirectoryEntry; import org.apache.poi…

python接口自动化(二)--什么是接口测试、为什么要做接口测试(详解)

简介 上一篇和大家一起科普扫盲接口后&#xff0c;知道什么是接口&#xff0c;接口类型等&#xff0c;对其有了大致了解之后&#xff0c;我们就回到主题-接口测试。 什么是接口测试 接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各…

“算力+运力”扇动双翼,制造算力时代的蝴蝶效应

8月18日-20日&#xff0c;第二届中国算力大会在宁夏银川成功举办。 今年以来&#xff0c;随着大模型、AIGC等新技术的火爆&#xff0c;站在舞台中央的算力承载了无尽的期待&#xff0c;发展数字经济需要以算力基础设施为前提&#xff0c;社会各界已经形成了共识。 与此同时&…

无涯教程-Android - DatePicker函数

Android Date Picker允许您在自定义用户界面中选择由日,月和年组成的日期。为此功能,android提供了DatePicker和DatePickerDialog组件。 在本教程中,我们将通过DatePickerDialog演示日期选择器的用法, DatePickerDialog是一个包含DatePicker的简单对话框。 为了显示DatePicker…

Leetcode110. 平衡二叉树

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给定一个二叉树&#xff0c;判断它是否是高度平衡的二叉树。 本题中&#xff0c;一棵高度平衡二叉树定义为&#xff1a; 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 题解&#xff…

【Go 基础篇】探索Go语言中的Map:数据的魔法盒子

嗨&#xff0c;各位Go语言的探索者们&#xff01;在我们的编程世界中&#xff0c;总会有一些特殊的工具能够让我们的生活变得更加便捷。而在Go语言中&#xff0c;Map就是这样一种神奇的数据结构。它就像是一个魔法盒子&#xff0c;可以帮助我们高效地存储和操作键值对数据。本文…

vue3中axios的使用方法

在Vue 3中使用axios发送HTTP请求的方法与Vue 2中基本相同。首先&#xff0c;需要安装axios库&#xff1a; npm install axios然后&#xff0c;在Vue组件中引入axios&#xff1a; import axios from axios;接下来&#xff0c;可以在Vue组件的方法中使用axios发送HTTP请求。例如…

算法通关村14关 | 数据流中位数问题

1. 数据流中位数问题 题目 LeetCode295: 中位数是有序列表中间的数&#xff0c;如果列表长度是偶数&#xff0c;中位数是中间两个数的平均值&#xff0c; 例如:[2,3,4]的中位数是3&#xff0c; [2,3]中位数是&#xff08;23&#xff09;/ 2 2.5 设计一个数据结构&#xff1a; …

2023.9.1 简单认识 JVM

目录 JVM 内存划分 本地方法栈 虚拟机栈 程序计数器 堆区 元数据区 JVM 类加载机制 加载 验证 准备 解析 初始化 类被加载的几种情况&#xff08;懒汉模式 ---> 只要被用到才会被加载&#xff09; 双亲委派模型 JVM 内存划分 JVM 是一个应用程序&#xff0c;在…