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

如何按嵌套数组内对象属性分组数组(Vanilla JS/Lodash实现)

按嵌套数组对象属性分组任务(原生JS/Lodash实现)

问题背景

需要将包含多经办人的任务数组,按每个经办人分组,让每个经办人对应自己的任务列表(仅包含任务标题和状态)。示例数据如下:

const taskList = [
  {
    "assignees": [
      { "name": "John", "uid": "id0001" },
      { "name": "Sally", "uid": "id0002" }
    ],
    "title": "Task 1",
    "status": "To do"
  },
  {
    "assignees": [{ "name": "John", "uid": "id0001" }],
    "title": "Task 2",
    "status": "To do"
  },
  {
    "assignees": [{ "name": "Sally", "uid": "id0002" }],
    "title": "Task 3",
    "status": "To do"
  }
];

期望得到的分组结果:

{
  "id0001": {
    "name": "John",
    "tasks": [
      { "title": "Task 1", "status": "To do" },
      { "title": "Task 2", "status": "To do" }
    ]
  },
  "id0002": {
    "name": "Sally",
    "tasks": [
      { "title": "Task 1", "status": "To do" },
      { "title": "Task 3", "status": "To do" }
    ]
  }
}

原代码问题分析

你之前用_.groupBy(taskList, task => task.assignees)失败的原因是:task.assignees是对象数组,JavaScript会自动将对象转换为字符串[object Object],导致所有任务被分到同一个分组下。


原生JavaScript实现

使用Array.prototype.reduce遍历任务列表,嵌套遍历每个经办人,逐步构建目标结构:

const groupedByAssignee = taskList.reduce((acc, task) => {
  // 遍历当前任务的所有经办人
  task.assignees.forEach(assignee => {
    const taskInfo = { title: task.title, status: task.status };
    // 初始化经办人分组(若不存在)
    if (!acc[assignee.uid]) {
      acc[assignee.uid] = { name: assignee.name, tasks: [] };
    }
    // 将任务添加到对应经办人的列表中
    acc[assignee.uid].tasks.push(taskInfo);
  });
  return acc;
}, {});

Lodash实现

通过展平任务-经办人关系→按UID分组→整理结构三步完成,也可以用链式调用简化:

链式调用版本

const result = _(taskList)
  // 展平:每个任务与每个经办人生成独立条目
  .flatMap(task => task.assignees.map(assignee => ({ assignee, task })))
  // 按经办人UID分组
  .groupBy('assignee.uid')
  // 整理成期望的结构
  .mapValues(items => ({
    name: items[0].assignee.name,
    tasks: items.map(({ task }) => ({ title: task.title, status: task.status }))
  }))
  // 获取最终结果
  .value();

分步拆解版本

// 1. 展平任务与经办人的对应关系
const flattened = _.flatMap(taskList, task => {
  return task.assignees.map(assignee => ({
    assignee,
    taskInfo: { title: task.title, status: task.status }
  }));
});

// 2. 按经办人UID分组
const grouped = _.groupBy(flattened, item => item.assignee.uid);

// 3. 整理为目标结构
const result = _.mapValues(grouped, items => ({
  name: items[0].assignee.name,
  tasks: items.map(item => item.taskInfo)
}));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 10:36:06