You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在对象属性内按嵌套子属性进行二级分组?

保留主键的二级嵌套分组实现

我有一个包含多个键的对象,每个键对应一个值数组,需要在保留主键的前提下,按数组元素中的嵌套值进行分组。

输入数据

{
  "foo1": [
    {"name": "foo1","subpart": {"part": "bar1"}},
    {"name": "foo1","subpart": {"part": "bar1"}},
    {"name": "foo1","subpart": {"part": "bar2"}},
    {"name": "foo1","subpart": {"part": "bar2"}},
    {"name": "foo1","subpart": {"part": "bar3"}},
    {"name": "foo1","subpart": {"part": "bar3"}}
  ],
  "foo2": [
    {"name": "foo2","subpart": {"part": "bar1"}},
    {"name": "foo2","subpart": {"part": "bar1"}},
    {"name": "foo2","subpart": {"part": "bar2"}},
    {"name": "foo2","subpart": {"part": "bar3"}},
    {"name": "foo2","subpart": {"part": "bar3"}}
  ]
}

期望输出

{
  "foo1": {
    "bar1": [
      {"name": "foo1","subpart": {"part": "bar1"}},
      {"name": "foo1","subpart": {"part": "bar1"}}
    ],
    "bar2": [
      {"name": "foo1","subpart": {"part": "bar2"}},
      {"name": "foo1","subpart": {"part": "bar2"}}
    ],
    "bar3": [
      {"name": "foo1","subpart": {"part": "bar3"}},
      {"name": "foo1","subpart": {"part": "bar3"}}
    ]
  },
  "foo2": {
    "bar1": [
      {"name": "foo2","subpart": {"part": "bar1"}},
      {"name": "foo2","subpart": {"part": "bar1"}}
    ],
    "bar2": [
      {"name": "foo2","subpart": {"part": "bar2"}}
    ],
    "bar3": [
      {"name": "foo2","subpart": {"part": "bar3"}},
      {"name": "foo2","subpart": {"part": "bar3"}}
    ]
  }
}

现有问题

当前的groupBy函数仅支持单级分组,直接调用会把所有数组元素合并到以subpart.part为键的分组中,丢失原有的foo1、foo2主键结构,不符合需求:

function groupBy<T>(arr: T[], fn: (item: T) => any) { 
  return arr.reduce<Record<string, T[]>>((prev, curr) => { 
    const groupKey = fn(curr); 
    const group = prev[groupKey] || []; 
    group.push(curr); 
    return { ...prev, [groupKey]: group }; 
  }, {}); 
}

// 调用后会丢失原主键,不符合预期
const grouped = groupBy(data, (x) => x.subpart.part)

解决方案

需要遍历原对象的每个主键,对每个主键对应的数组单独执行分组操作,最终保留原结构。可以基于现有groupBy函数封装一个处理嵌套结构的函数:

// 保留原有的分组函数
function groupBy<T>(arr: T[], fn: (item: T) => any) {
  return arr.reduce<Record<string, T[]>>((prev, curr) => {
    const groupKey = fn(curr);
    prev[groupKey] = prev[groupKey] || [];
    prev[groupKey].push(curr);
    return prev;
  }, {});
}

// 新增处理整个对象的函数,保留原主键
function groupNestedBy<T>(obj: Record<string, T[]>, fn: (item: T) => any) {
  const result: Record<string, Record<string, T[]>> = {};
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      result[key] = groupBy(obj[key], fn);
    }
  }
  return result;
}

调用方式

const grouped = groupNestedBy(data, (x) => x.subpart.part);

该实现会遍历原对象的每个主键(如foo1、foo2),对每个主键下的数组执行嵌套值分组,最终输出与期望结构完全一致的结果。

内容的提问来源于stack exchange,提问作者Bouke Groenescheij

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 08:01:21