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

如何按多层嵌套值分组任务对象数组?

多级分类任务数组的结构化处理方案

问题背景

我有一个包含任务的对象数组,每个任务归属于一级分类(primary_category)和二级分类(secondary_category):

let tasks = [
  {
    id: 1,
    name: 'Cleanup desk',
    primary_category: {
      id: 1,
      name: 'Indoor'
    },
    secondary_category: {
      id: 2,
      name: 'Surfaces'
    }
  },
  {
    id: 2,
    name: 'Cleanup office floors',
    primary_category: {
      id: 1,
      name: 'Indoor'
    },
    secondary_category: {
      id: 3,
      name: 'Ground'
    }
  },
  {
    id: 3,
    name: 'Water plants',
    primary_category: {
      id: 2,
      name: 'Outdoor'
    },
    secondary_category: {
      id: 3,
      name: 'Irrigation'
    }
  }
];

需要将数组转换为一级分类 -> 二级分类 -> 任务的层级结构,用于前端折叠面板组件,期望得到的最终结构如下:

let tasks_categorized = [
  {
    id: 1,
    name: 'Indoor',
    secondary_categories: [
      {
        id: 2,
        name: 'Surfaces',
        tasks: [
          {
            id: 1,
            name: 'Cleanup desk'
          }
        ]
      },
      {
        id: 3,
        name: 'Ground',
        tasks: [
          {
            id: 2,
            name: 'Cleanup office floors'
          }
        ]
      }
    ]
  },
  {
    id: 2,
    name: 'Outdoor',
    secondary_categories: [
      {
        id: 3,
        name: 'Irrigation',
        tasks: [
          {
            id: 3,
            name: 'Water plants'
          }
        ]
      }
    ]
  }
];

尝试使用lodash的groupBy方法,但该方法无法直接实现这种多级嵌套的分组逻辑,求可行的解决办法。


解决方案

方案一:原生JavaScript实现

通过遍历任务数组,利用Map快速查找已存在的分类,逐步构建层级结构,无需依赖第三方库:

function categorizeTasks(tasks) {
  const result = [];
  const primaryCategoryMap = new Map();

  tasks.forEach(task => {
    const { primary_category, secondary_category, id, name } = task;
    
    // 初始化一级分类(不存在则创建)
    if (!primaryCategoryMap.has(primary_category.id)) {
      const primaryItem = {
        id: primary_category.id,
        name: primary_category.name,
        secondary_categories: []
      };
      primaryCategoryMap.set(primary_category.id, primaryItem);
      result.push(primaryItem);
    }
    const currentPrimary = primaryCategoryMap.get(primary_category.id);
    
    // 初始化二级分类(不存在则创建)
    let currentSecondary = currentPrimary.secondary_categories.find(sc => sc.id === secondary_category.id);
    if (!currentSecondary) {
      currentSecondary = {
        id: secondary_category.id,
        name: secondary_category.name,
        tasks: []
      };
      currentPrimary.secondary_categories.push(currentSecondary);
    }
    
    // 将当前任务添加到对应二级分类下
    currentSecondary.tasks.push({ id, name });
  });

  return result;
}

// 调用示例
const categorizedTasks = categorizeTasks(tasks);
console.log(categorizedTasks);

方案二:结合lodash实现多级分组

如果项目中已经使用lodash,可以先通过groupBy完成基础分组,再逐层转换为目标结构:

// 确保已引入lodash
const _ = require('lodash');

function categorizeTasksWithLodash(tasks) {
  // 第一步:按一级分类ID分组
  const groupedByPrimary = _.groupBy(tasks, task => task.primary_category.id);
  
  // 转换为一级分类数组
  return Object.values(groupedByPrimary).map(primaryGroup => {
    // 提取一级分类的基础信息
    const primaryInfo = primaryGroup[0].primary_category;
    // 第二步:对当前一级分类下的任务按二级分类ID分组
    const groupedBySecondary = _.groupBy(primaryGroup, task => task.secondary_category.id);
    
    // 转换为二级分类数组
    const secondaryCategories = Object.values(groupedBySecondary).map(secondaryGroup => {
      const secondaryInfo = secondaryGroup[0].secondary_category;
      // 提取任务的id和name字段
      const taskList = secondaryGroup.map(({ id, name }) => ({ id, name }));
      return { ...secondaryInfo, tasks: taskList };
    });
    
    return { ...primaryInfo, secondary_categories: secondaryCategories };
  });
}

// 调用示例
const categorizedTasks = categorizeTasksWithLodash(tasks);
console.log(categorizedTasks);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 17:45:40