首页 > 编程语言 >JavaScript 的新数组分组方法

JavaScript 的新数组分组方法

时间:2024-11-30 22:57:41浏览次数:7  
标签:name age JavaScript 28 peopleByAge person 分组 数组 groupBy

对数组中的项目进行分组,你可能已经做过很多次了。每次都会手动编写一个分组函数,或者使用 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 并亲自尝试这些新方法吧。

标签:name,age,JavaScript,28,peopleByAge,person,分组,数组,groupBy
From: https://www.cnblogs.com/skonw/p/18579066

相关文章

  • 【C语言】二维数组的声明
    一、1.在被调用函数的形参数组声明可以省略第一维的大小,第二维不可省略2.实参数组第一维第二维都需要#include<stdio.h>intmain(){ inta[][]; //Error intb[1][]; //Error intc[][1]; //Error intd[1][1]; return0;}voidf(inta[][]) //Error{ }v......
  • 大学生HTML期末大作业——HTML+CSS+JavaScript培训机构(画室)
    HTML+CSS+JS【培训机构】网页设计期末课程大作业web前端开发技术web课程设计网页规划与设计......
  • 前端:JavaScript (学习笔记)【2】
    目录一,数组的使用1,数组的创建  [ ]2,数组的元素和长度3,数组的遍历方式4,数组的常用方法二,JavaScript中的对象1,常用对象(1)String和java中的String很类似,的常用方法(2) Number的常用属性和方法(包装类)   [1]属性   [2 ]数学方法(3)Math对象(4)Date......
  • JavaScript 中的原型和原型链
    JavaScript中的原型和原型链也是一个相对较难理解透彻的知识点,下面结合详细例子来进行说明:一、原型的概念在JavaScript中,每个函数都有一个prototype属性,这个属性指向一个对象,这个对象就是所谓的“原型对象”。当通过构造函数创建一个新的实例对象时,该实例对象会自动......
  • 编一个程序,从键盘上输入一串符号(以回车键为结束),将其以字符串形式存入一维字符数组,然后
    大学作业,运行不了就把每个for循环里面的int提出来,括号内保留i就行了!!!!!多的我不说了,代码放地下自取自拿,某人在这里求个赞,陆续会更新实验3-5,所有作业都有复制(自取)版和详解版,记得关注,谢谢各位:tips:gets在C11版本被删去,目前仅仅是用于大学计算机,正式版我也放在末尾并说明区别自取版:......
  • C# mvc +angular+ $http+ web api + javascript
    下面分享在ASP.NETMVC环境中,使用angular的$http访问WebAPI,javascript可写成一个独立js代码文档,再引入MVC视图里,也可以直接写在视图内。多少内容与下2篇有得参考:C#mvc+axios+webapi+javascript https://www.cnblogs.com/insus/p/18577591asp.netmvc视图传递数据至另......
  • leetcode 2289. 使数组按非递减顺序排列 未解决
    leetcode2289.使数组按非递减顺序排列这道题远没有想象中的简单,如果用暴力常规方法,数据量大的情况下会超时暴力解1:classSolution{public:inttotalSteps(vector<int>&nums){intsize=nums.size();intres=0;intformer=0,now=......
  • 洛谷 P1680 奇怪的分组(组合数学)
    题目传送门https://www.luogu.com.cn/problem/P1680解题思路这是一道组合数学题。既然题目说了第  个组要大于  个人,那我们不妨先给每个组分  个人。但题目说了是大于  个人,我们只给每个组分了  个人,所以还得分几个人。那么问题就变成了:对于剩下的  个人,我们......
  • 数组扩容
    一、思路:新建一个数组,将以前的数组值依次放入新数组中,在新数组中添加元素;让以前数组等于新数组,以前数组的数据空间销毁;数组反转同理二、要求:实现动态的给数组添加元素效果,实现对数组扩容。ArrayAdd.java1.原始数组使用静态分配int[]arr={1,2,3}2.增加的元素4,直接放在数组的......
  • 泛型数组与hashmap
    5.3泛型数组列表5.3.1访问数组元素列表基本类型和包装类是等价的可以用int接受Integer的importjava.util.*;publicclasstext1{publicstaticvoidmain(String[]args)throwsException{String[]arr=newString[100];//长度定死ArrayList<S......