JavaScript 中 Object.groupBy 与 Map.groupBy 标准用法及多场景实现

作者:小括号时间:2026-11-01 01:13:47浏览:374

本文详解 JavaScript 中 Object.groupBy 与 Map.groupBy 的标准用法,涵盖 TC39 提案进展与环境支持。通过从零实现基于 Key 和通用函数的分组逻辑,对比 Lodash 与 RxJS 中的分组方案,并展示如何在函数式编程中自定义操作符,全面解析数据处理中的分组技巧。

一、前言

在数据处理与分析领域,对数据进行分组是一项极为常见且核心的功能,无论是日常业务开发还是技术面试中,其应用场景都十分广泛。特别是在函数式编程范式下, 更是不可或缺的基础工具。目前,该功能已被纳入 JavaScript 语言标准,成为原生支持的能力。

二、介绍

groupBy 函数是一个用于对 数组元素 进行 分组 的实用工具。通过 groupBy,我们可以灵活指定分组条件,将数组中的元素划分为不同的组,从而满足复杂的数据处理或界面展示需求。

三、标准

一、前言

该功能源自 TC39 提案:proposal-array-grouping: tc39.es/proposal-array-grouping/#sec-scope

Object.groupBy

Object.groupBy(items, callbackFn) // 语法,第一个参数是可迭代对象,第二参数是回调函数

Map.groupBy

Map.groupBy(items, callbackFn) // 语法,第一个参数是可迭代对象,第二参数是回调函数

四、环境支持

一、前言

五、Object.groupBy 示例

const data = [
  { id: 1, type: 'A' },
  { id: 2, type: 'B' },
  { id: 3, type: 'A' },
  { id: 4, type: 'C' },
  { id: 5, type: 'B' },
];
const groupType = Object.groupBy(data, 'type') // ❌ 第二个参数必须是函数
const groupType = Object.groupBy(data, (item) => item.type) // ✅ 按照类型进行分类, 并且 type 就是 group 的 key 值。
// {
//   A: [{…}, {…}]
//   B: [{…}, {…}]
//   C: [{…}]
/ }

六、实现一个按照给定 key 进行分组

虽然通用函数具备更广泛的适用性,但其实现复杂度略高于直接传递属性名的方式。这里展示一种通过传递属性名来实现 的方法:

function groupBy(arr, key) {
  return arr.reduce((acc, obj) => {
    const groupKey = obj[key];
    acc[groupKey] = acc[groupKey] || [];
    acc[groupKey].push(obj);
    return acc;
  }, {});
}

// data 复用以上的 data
groupBy(data, 'type') // 输出结果与 Object.groupBy 一致

实现的核心思想是利用 reduce 进行 累加。从初始化一个空对象 {} 开始,随后在对象上为对应的 key 赋值空数组,若元素符合该 key,则将其归入此分组。

七、实现一个通用的 groupBy

在掌握基于 key 的实现方式后,进一步实现支持自定义函数的通用 便相对容易:

type KeyFunc<T> = (obj: T) => string

export function groupByWithFn<T>(
  array: T[],
  keyFunc: KeyFunc<T>
): Record<string, T[]> {
  return array.reduce((acc: Record<string, T[]>, obj: T) => {
    const key: string = keyFunc(obj)
    if (!acc[key]) {
      acc[key] = []
    }
    acc[key].push(obj)
    return acc
  }, {})
}

此处使用 TypeScript 实现,主要目的是约束类型。其本质逻辑非常直观:利用 keyFunc 对当前的 obj 执行以获取 key,若未获取到对应的 key,则初始化一个空数组,并将数据填充进去。通过重复累积这一过程完成分组。

八、lodash 中的 groupBy

_.groupBy(data, (item) => item.type)

在 lodash 库中, 被放置在 collection 集合模块中,而非仅针对数组。其使用方式与上述原生实现基本一致。

九、rxjs groupBy

若涉及函数式编程,RxJS 中的数据操作自然不可或缺。RxJS 原生的 groupBy 无法直接等同于 JS 中的 功能,但我们可以组合操作符或自定义操作符来实现。以下是实现一个自定义操作符 customGroupBy 的示例:

import { Observable, of } from 'rxjs';
import { map, mergeMap, reduce } from 'rxjs/operators';

// 自定义 groupBy 操作符
function customGroupBy(keySelector) {
  return function (source) {
    return new Observable((observer) => {
      source.pipe(
        mergeMap((arr) => arr),
        reduce((acc, val) => {
          const key = keySelector(val);
          acc[key] = acc[key] || [];
          acc[key].push(val);
          return acc;
        }, {})
      ).subscribe({
        next: (result) => {
          observer.next(result);
          observer.complete();
        },
        error: (err) => observer.error(err),
      });
    });
  };
}

of([
    { id: 1, type: 'A' },
    { id: 2, type: 'B' },
    { id: 3, type: 'A' },
    { id: 4, type: 'C' },
    { id: 5, type: 'B' },
  ]).pipe(
  customGroupBy((obj) => obj.type)
).subscribe({
  next: (v) => {console.log(v)}
});

customGroupBy 操作符接受一个函数作为参数,该函数是一个闭包,包含了 of 操作符中的静态数据。customGroupBy 是典型的自定义操作符实现,source 即为由 of 创建的静态可观察对象。后续逻辑同样利用 reduce 进行累加计算,最终对外输出数据。

十、groupBy 其他

  • 在 SQL 中,GROUP BY 语句用于将行分组为汇总行。
  • 在 Python 中,可以使用 itertools.groupby 对可迭代对象进行分组。
  • 在一些数据处理工具中,例如 Excel 以及 Python 的相关库,也提供了类似功能。

十一、小结

本文主要介绍了 JavaScript 中 函数的实用特性。内容从 ES 标准草案出发,涵盖了自己实现简单的 ,以及 lodash 和 RxJS 中实现 效果的方法。在函数式编程中, 的实用价值极高,在数据处理领域有着广泛的应用。

到此这篇关于 JavaScript 中常用数据处理函数 groupBy 的用法详解的文章就介绍到这了,更多相关 JavaScript groupBy 内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

作者最新文章