如何按树形部门标题路径分组SubjectDto集合?
问题描述
我拥有一组部门ID,用于获取对应的Subject。我希望按照部门标题路径对这些Subject进行分组。例如,假设有Office、Room1、Room2三个部门,Office是Room1和Room2的父部门,预期分组键为"Office"、"Office/Room1"、"Office/Room2"。
现有代码仅能按Department.Title分组,无法实现层级路径分组:
var departmentsIds = _parameters.ShowSubjectsOfNestedDepartments ? await GetDepartmentsIdsWithNested() : _parameters.DepartmentIDs;
var groupedSubjects = ( await _subjectClient .GetByDepartmentsIds( departmentsIds ) .Unwrap() ) .GroupBy( subject => subject.Department.Title );
相关类定义:
public class SubjectDto { public string Id { get; set; } public DepartmentDigestDto Department { get; set; } } public class DepartmentDigestDto { [JsonProperty( PropertyName = "id" )] [JsonRequired] public string Id { get; set; } [JsonProperty( PropertyName = "title" )] public string Title { get; set; } [JsonProperty( PropertyName = "parent_department_id" )] public string ParentDepartmentId { get; set; } }
解决方案
要实现按部门标题路径分组,核心是先构建每个部门的完整层级路径,再用该路径作为分组键,具体步骤如下:
收集所有相关部门数据
首先需要获取所有涉及的部门(包括父部门)的完整信息,确保能追溯到根部门:// 先获取所有目标Subject var subjects = await _subjectClient.GetByDepartmentsIds(departmentsIds).Unwrap(); // 收集所有需要查询的部门ID:包括Subject所属部门,以及它们的父部门 var allDepartmentIds = subjects.Select(s => s.Department.Id) .Union(subjects.Select(s => s.Department.ParentDepartmentId) .Where(id => !string.IsNullOrEmpty(id))) .ToList(); // 批量获取所有部门详情(如果没有批量接口,可循环调用单个查询接口) var allDepartments = new Dictionary<string, DepartmentDigestDto>(); foreach (var id in allDepartmentIds) { if (!allDepartments.ContainsKey(id)) { var dept = await _departmentClient.GetByIdAsync(id).Unwrap(); allDepartments.Add(id, dept); } }编写路径生成方法
实现一个迭代方法,从当前部门向上追溯父部门,拼接出完整的标题路径:private string GetDepartmentPath(string departmentId, Dictionary<string, DepartmentDigestDto> allDepartments) { if (!allDepartments.TryGetValue(departmentId, out var currentDept)) { return currentDept?.Title ?? string.Empty; } var pathParts = new List<string>(); // 向上遍历所有父部门 while (currentDept != null) { pathParts.Add(currentDept.Title); if (string.IsNullOrEmpty(currentDept.ParentDepartmentId)) break; allDepartments.TryGetValue(currentDept.ParentDepartmentId, out currentDept); } // 反转得到从根到当前部门的顺序,再拼接成路径 pathParts.Reverse(); return string.Join("/", pathParts); }按路径分组Subject
调用路径生成方法,以部门标题路径作为分组键:var groupedSubjects = subjects.GroupBy(subject => GetDepartmentPath(subject.Department.Id, allDepartments));
优化建议
- 若部门数据不频繁变动,可缓存部门的路径映射,避免重复计算和接口调用。
- 如果有部门树结构批量查询接口,优先使用该接口,减少单次接口调用次数。
内容的提问来源于stack exchange,提问作者Anthony
相关产品推荐
相关产品推荐

