JavaScript 的新数组分组方法
对数组中的项目进行分组,你可能已经做过很多次了。每次都会手动编写一个分组函数,或者使用 lodash 的 groupBy 函数。
好消息是,JavaScript 现在有了分组方法,所以你再也不必这样做了。Object.groupBy 和 Map.groupBy 这两个新方法将使分组变得更简单,并节省我们的时间或依赖性。
以前的做法
假设你有一个代表人的对象数组,你想按年龄对它们进行分组。你可以这样使用 forEach 循环:
const people = [
{ name: "Alice", age: 28 },
{ name: "Bob", age: 30 },
{ name: "Eve", age: 28 },
];
const peopleByAge = {};
people.forEach((person) => {
const age = person.age;
if (!peopleByAge[age]) {
peopleByAge[age] = [];
}
peopleByAge[age].push(person);
});
console.log(peopleByAge);
/*
{
"28": [{"name":"Alice","age":28}, {"name":"Eve","age":28}],
"30": [{"name":"Bob","age":30}]
}
*/
或者可以像这样来使用reduce:
const peopleByAge = people.reduce((acc, person) => {
const age = person.age;
if (!acc[age]) {
acc[age] = [];
}
acc[age].push(person);
return acc;
}, {});
无论哪种方法,代码都略显笨拙。你总是要检查对象是否存在分组键,如果不存在,就用一个空数组来创建它。然后再将项目推入数组。
使用Object.groupBy
有了新的 Object.groupBy 方法,你就可以像这样得出结果:
const peopleByAge = Object.groupBy(people, (person) => person.age);
简单多了!不过也有一些需要注意的地方。
Object.groupBy 返回一个空原型对象。这意味着该对象不继承 Object.prototype 的任何属性。这很好,因为这意味着你不会意外覆盖 Object.prototype 上的任何属性,但这也意味着该对象没有你可能期望的任何方法,如 hasOwnProperty 或 toString。
const peopleByAge = Object.groupBy(people, (person) => person.age);
console.log(peopleByAge.hasOwnProperty("28"));
// TypeError: peopleByAge.hasOwnProperty is not a function
传递给 Object.groupBy 的回调函数应返回字符串或Symbol。如果返回其他内容,则将强制转为字符串。
在我们的示例中,我们一直以数字形式返回age,但在结果中却被强制转为字符串。尽管如此,你仍然可以使用数字访问属性,因为使用方括号符号也会将参数强制为字符串。
console.log(peopleByAge[28]);
// => [{"name":"Alice","age":28}, {"name":"Eve","age":28}]
console.log(peopleByAge["28"]);
// => [{"name":"Alice","age":28}, {"name":"Eve","age":28}]
使用Map.groupBy
除了返回 Map 之外,Map.groupBy 的功能与 Object.groupBy 几乎相同。这意味着你可以使用所有常用的 Map 函数。这也意味着你可以从回调函数返回任何类型的值。
const ceo = { name: "Jamie", age: 40, reportsTo: null };
const manager = { name: "Alice", age: 28, reportsTo: ceo };
const people = [
ceo,
manager,
{ name: "Bob", age: 30, reportsTo: manager },
{ name: "Eve", age: 28, reportsTo: ceo },
];
const peopleByManager = Map.groupBy(people, (person) => person.reportsTo);
在本例中,我们是按照向谁汇报工作来对人员进行分组的。请注意,要从该 Map 中按对象检索项目,对象必须具有相同的引用。
peopleByManager.get(ceo);
// => [{ name: "Alice", age: 28, reportsTo: ceo }, { name: "Eve", age: 28, reportsTo: ceo }]
peopleByManager.get({ name: "Jamie", age: 40, reportsTo: null });
// => undefined
在上面的示例中,第二行使用了一个看起来像 ceo 对象的对象,但它并不是同一个对象,因此它不会从 Map 中返回任何内容。要想成功地从 Map 中获取项目,请确保你保留了要用作键的对象的引用。
何时可用
这两个 groupBy 方法是 TC39 提议的一部分,目前处于第三阶段。这意味着它很有可能成为一项标准,因此也出现了一些实施方案。
Chrome 浏览器 117 版本刚刚推出了对这两种方法的支持,而 Firefox 浏览器 119 版本也发布了对这两种方法的支持。Safari 以不同的名称实现了这些方法,我相信他们很快就会更新。既然 Chrome 浏览器中出现了这些方法,就意味着它们已在 V8 中实现,因此下次 V8 更新时,Node 中也会出现这些方法。
为什么使用静态方法
你可能会问,为什么要以 Object.groupBy 而不是 Array.prototype.groupBy 的形式来实现呢?根据该提案,有一个库曾经用一个不兼容的 groupBy 方法对 Array.prototype 进行了猴子补丁。在考虑新的应用程序接口时,向后兼容性非常重要。几年前,在尝试实现 Array.prototype.flatten 时,这一点在一次被称为 SmooshGate 的事件中得到了强调。
幸运的是,使用静态方法似乎更有利于未来的可扩展性。当 Record 和 Tuples 提议实现时,我们可以添加一个 Record.groupBy 方法,用于将数组分组为不可变的记录。
总结
将项目分组显然是我们开发人员的一项重要工作。目前,每周从 npm 下载 lodash.groupBy 的次数在 150 万到 200 万之间。很高兴看到 JavaScript 填补了这些空白,让我们的工作变得更加轻松。
现在,下载 Chrome 117 并亲自尝试这些新方法吧。
JavaScript 的新数组分组方法的更多相关文章
- JavaScript中的数组Array方法
push(),pop()方法 push(),pop()方法也叫栈方法,push()可以理解成,向末尾推入,而pop()恰好相反,可以理解成从末尾移除(取得). var nums=[1,2,3,4]; ...
- javascript 克隆对象/数组的方法 clone()
1 11 javascript 克隆对象/数组的方法 clone() 1 demo: code: 1 var Obj; 2 let clone = (Obj) => { 3 var buf; ...
- javascript常见操作数组的方法
在 JavaScript 中,判断一个变量的类型尝尝会用 typeof 运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 "obj ...
- JavaScript中操作数组的方法
JavaScript Array 对象 对数组操作的方法分为两种 一种是会改变原始数组的变异方法,还有一种是不会改变原始数组的非变异方法. 总结 巧记 Push() 尾部添加 pop() 尾部删除 U ...
- JavaScript中Array数组的方法
查找: indexOf.lastIndexOf 迭代:every.filter.forEach.map.somereduce.reduceRight 用法: /* 1 查找方法: * arr.inde ...
- js中实现截取数组的后几个元素作为一个新数组的方法
有时候我们会遇到这种需求,截取数组中后5个元素作为一个新数组,且顺序不能变.数组中的slice()方法和splice()方法都可以实现这样的操作. const arr = [1,2,7,2,6,0,3 ...
- javaScript中的数组迭代方法
ECMAScript5为数组定义了5个迭代方法. 每个方法都接收两个参数:要在每一项上运行的函数 和 (可选的)运行该函数的作用域对象. 传入这些方法中的函数会接收三个参数:数组项的值,该项在数组 ...
- JavaScript中对象数组去重方法
在一次对后端返回的对象数组的操作时想通过indexOf()或者includes()的方法来实现对对象数组的去重但是行不通,因为用indexOf()返回的都是-1,一下记录两种对象数组(更具指定属性)去 ...
- javascript打开新页面的方法
方案一: A标签: 这里要注意target的设置,_Blank是指新窗口,也可以用js来模拟创建. <a href="http://www.cnblogs.com" targ ...
- es5和es6创建新数组的方法
//es5 let array = Array(5) let array = [] //es6 1.let array = Array.of(1,2,3,4,5) 2.let array = Arra ...
随机推荐
- Linux_sqlcmd或者是Cloudquery连接SQLSERVER2012的问题解决
Linux_sqlcmd或者是Cloudquery连接SQLSERVER2012的问题解决 背景 最近想使用shell脚本给SQLServer数据库插入数据,但是发现了报错 同时进行CLoudquer ...
- [转帖]ASH、AWR、ADDM区别联系
==================================================================================================== ...
- [转帖]JVM——内存区域:运行时数据区域详解
https://www.jianshu.com/p/cded765cfd1b 关注:CodingTechWork,一起学习进步. 引言 我们经常会被问到一个问题是Java和C++有何区别?我们除了 ...
- [转帖]数据库篇-MySql架构介绍
https://zhuanlan.zhihu.com/p/147161770 公众号-坚持原创,码字不易.加微信 : touzinv 关注分享,手有余香~ 本篇咱们也来聊聊mysql物理和逻辑架构,还 ...
- [转帖]CentOS8安装MySQL8详细教程,爬坑必备
https://www.ab62.cn/article/23022.html 安装环境 CentOS:8.5.2111MySQL:8.0.30 MySQL Community Server 安装过程 ...
- Linux 安装宋体字体的简单办法
1. 今天同事说测试环境(CentOS) 打印有异常,无法将汉字正常打印出来. 2. 开发同事提供的思路是安装上宋体的字体再进行尝试,并且给出了一个解决方案的地址: https://blog.csdn ...
- [转贴]win10临时修改、永久cmd 编码格式的方法
https://www.jianshu.com/p/40a9fbaf1cac cmd 前言 有时候,运行一些命令行程序某些字符无法正常显示,常见的就是方块,或者是火星文字都是由于 cmd 程序的默 ...
- clickhouse 优化实践,万级别QPS数据毫秒写入和亿级别数据秒级返回 | 京东云技术团队
1.背景 魔笛活动平台目前在采集每个活动的用户行为数据并进行查询,解决线上问题定位慢,响应不及时的问题,提升客诉的解决效率.目前每天采集的数据量5000万+,一个月的数据总量15亿+,总数据量40亿+ ...
- 2023年了,做SEO还有必要吗?
作者:京东科技 吴磊 搜索引擎工作原理 在搜索引擎网站的后台会有一个非常庞大的数据库,里面存储了海量的关键词,而每个关键词又对应着很多网址,这些网址是被称之为"搜索引擎蜘蛛"或&q ...
- echarts 设置legend样式
设置legend样式 legend: { x: 'center', data: ['班车', '包车'], icon: "circle", // 这个字段控制形状 类型包括 cir ...