Как поменять группируемое свойство?

Рейтинг: 0Ответов: 1Опубликовано: 10.03.2023

На вход я принимаю список id подразделений, по которым я получаю список подразделений и их субъектов. Код выглядит достаточно просто:

private async Task<IEnumerable<string>> GetDepartmentsIdsWithNested()
{
    var parentsDepartments = await _departmentClient
         .GetByParentsIds( _parameters.DepartmentIDs )
         .Unwrap();

    var ids = parentsDepartments
         .SelectMany( x => new[] { x.Id, x.ParentDepartment.Id } )
         .Distinct();

    return ids;
}

private async Task<StaffDataSet> PrepareDataSet()
{
    var dataSet = new StaffDataSet();

    var departmentsIds = _parameters.ShowSubjectsOfNestedDepartments
         ? await GetDepartmentsIdsWithNested()
         : _parameters.DepartmentIDs;

    var groupedSubjects = ( await _subjectClient
           .GetByDepartmentsIds( departmentsIds )
           .Unwrap() )
         .GroupBy( subject => subject.Department.Title );

    foreach ( var group in groupedSubjects )
        foreach ( var subject in group )
        {
            dataSet.Staff.AddStaffRow(
                Title: subject.GetSubjectFullName(),
                AccessGroup: GetAccessGroupFormattedString( subject.AccessGroups ),
                TabNumber: subject.Data.FromJson<SubjectData>()?.PersonnelNumber,
                Identifier: GetIdentifierFormattedString( subject.Identifiers ),
                Department: group.Key );
        }

    return dataSet;
}

GroupedSubjects - это субъекты, которые были сгруппированы по title департамента, но хотелось бы сгруппировать по пути.

Что я имею ввиду: допустим, у меня есть подразделение "Home", а у него еще два "Class1", "Class2". Субъекты сгруппируются по Home, Class1, Class2, а я хочу вот так: Home, Home/Class1, Home/Class2.

Ответы

▲ 1

Как я советовал уже, чтобы собрать все пути сверху вниз, надо

  1. Построить дерево (по сути группировать по parentId)
  2. Выполнить обход дерева. Самый простой вариант будет обход в глубину здесь

Сначала данные

var data = new DepartmentDigestDto[]
{
    new DepartmentDigestDto() {Id = "1", Title = "Office" },
    new DepartmentDigestDto() {Id = "2", Title = "First Room", ParentDepartmentId = "1" },
    new DepartmentDigestDto() {Id = "3", Title = "Second Room", ParentDepartmentId = "2" },
};

Группируем по родителю, получаается словарь, где ключ - айдишник родителя, значение - список узлов под родителем.

var tree = data.Where(x => !string.IsNullOrEmpty(x.ParentDepartmentId))
                .GroupBy(x => x.ParentDepartmentId)
                .ToDictionary(x => x.Key, x => x.ToList());

Функция обхода в глубину по дереву выглядит как то так, ничего особенного, самый обычный вариант рекурсивного обхода

private void GetAllPaths(DepartmentDigestDto root,
        Dictionary<string, List<DepartmentDigestDto>> tree,
        List<string> currentPath,
        List<string> results)
{
    currentPath.Add(root.Title);
    results.Add(string.Join("/", currentPath));
    if (tree.ContainsKey(root.Id))
    {
        foreach (var child in tree[root.Id])
            GetAllPaths(child, tree, currentPath, results);
    }
    currentPath.RemoveAt(currentPath.Count - 1);
}

Ну осталось вызвать функцию для каждого корня (то есть узла без родителя)

var paths = new List<string>();
foreach (var root in data.Where(x => string.IsNullOrEmpty(x.ParentDepartmentId)))
    GetAllPaths(root, tree, new List<string>(), paths);

Вывод результата

foreach (var path in paths)
    Console.WriteLine(path);

Что в консоли:

Office
Office/First Room
Office/First Room/Second Room