C# Сортировка списка Родителя / Дочернего для получения плоского вывода - PullRequest
1 голос
/ 21 февраля 2020

У меня есть эта модель:

public class Node 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int? ParentId { get; set; }
}

У меня есть следующие данные, полученные из запроса к базе данных:

        nodes.Add(new Node { Id = 1, Name = "Node #1", ParentId = null });
        nodes.Add(new Node { Id = 2, Name = "Node #2", ParentId = 1 });
        nodes.Add(new Node { Id = 3, Name = "Node #3", ParentId = 2 });
        nodes.Add(new Node { Id = 4, Name = "Node #4", ParentId = null });
        nodes.Add(new Node { Id = 5, Name = "Node #5", ParentId = 2 });
        nodes.Add(new Node { Id = 6, Name = "Node #6", ParentId = 2 });
        nodes.Add(new Node { Id = 7, Name = "Node #7", ParentId = 1 });
        nodes.Add(new Node { Id = 8, Name = "Node #8", ParentId = 5 });
        nodes.Add(new Node { Id = 9, Name = "Node #9", ParentId = 4 });
        nodes.Add(new Node { Id = 10, Name = "Node #10", ParentId = 4 });

Я хотел бы отсортировать список и сохранить плоскую структуру , Результат, который я ожидаю, таков:

        // 1  - Node #1  => NULL
        // 2  - Node #2  => 1
        // 3  - Node #3  => 2
        // 5  - Node #5  => 2
        // 8  - Node #8  => 5
        // 6  - Node #6  => 2
        // 7  - Node #7  => 1
        // 4  - Node #4  => NULL
        // 9  - Node #9  => 4
        // 10 - Node #10 => 4

Я имел в виду этот Ответ Stackoverflow , но я не получил желаемый результат.

Любая помощь?

Ответы [ 3 ]

2 голосов
/ 21 февраля 2020

Вот как я бы это сделал:

var nodes = new List<Node>()
{
    new Node { Id = 1, Name = "Node #1", ParentId = null },
    new Node { Id = 2, Name = "Node #2", ParentId = 1 },
    new Node { Id = 3, Name = "Node #3", ParentId = 2 },
    new Node { Id = 4, Name = "Node #4", ParentId = null },
    new Node { Id = 5, Name = "Node #5", ParentId = 2 },
    new Node { Id = 6, Name = "Node #6", ParentId = 2 },
    new Node { Id = 7, Name = "Node #7", ParentId = 1 },
    new Node { Id = 8, Name = "Node #8", ParentId = 5 },
    new Node { Id = 9, Name = "Node #9", ParentId = 4 },
    new Node { Id = 10, Name = "Node #10", ParentId = 4 },
};

var lookup = nodes.ToLookup(x => x.ParentId);

IEnumerable<Node> Flatten(int? parentId)
{
    foreach (var node in lookup[parentId])
    {
        yield return node;
        foreach (var child in Flatten(node.Id))
        {
            yield return child;
        }
    }   
}

var output = Flatten(null).ToArray();

Эта небольшая рекурсия дает мне:

Flattened List

0 голосов
/ 21 февраля 2020

Я думаю, вы хотите это

 nodes.OrderBy(n => n.ParentID ?? n.Id)
      .ThenBy(n => n.Id);
0 голосов
/ 21 февраля 2020

Вы можете попробовать создать рекурсивный запрос в LINQ, используя SelectMany как:

IEnumerable<Node> Recurcive(List<Node> nodeList, int? parentId)
{
    return nodeList
        .Where(x => x.ParentId == parentId)
        .SelectMany(x =>
                  new[] { new Node
                    { Id = x.Id, Name = x.Name, ParentId = x.ParentId } }
                        .Concat(Recurcive(nodeList, x.Id)));
}

foreach (var node in Recurcive(nodes, null))
    Console
     .WriteLine($"Id : {node.Id}\t, Name = {node.Name}\t, Parent = {node.ParentId}");

Вывод:

//Id: 1  , Name = Node #1        , Parent =
//Id: 2  , Name = Node #2        , Parent = 1
//Id: 3  , Name = Node #3        , Parent = 2
//Id: 5  , Name = Node #5        , Parent = 2
//Id: 8  , Name = Node #8        , Parent = 5
//Id: 6  , Name = Node #6        , Parent = 2
//Id: 7  , Name = Node #7        , Parent = 1
//Id: 4  , Name = Node #4        , Parent =
//Id: 9  , Name = Node #9        , Parent = 4
//Id: 10 , Name = Node #10       , Parent = 4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...