簡體   English   中英

使用父引用從對象創建嵌套的項列表

[英]Create a nested list of items from objects with a parent reference

我正在使用C# ,我有一個具有可空父ID屬性的項目列表。

我需要將其轉換為具有子女列表的項目列表,並繼續下去,直到沒有項目為止。

我現有的課

public class Item
{
    public int Id { get; set; }
    public int? ParentId { get; set; }
}

我的第一個想法......

創建一個類

public class ItemWithChildren
{
    public Item Item { get; set; }
    public List<ItemWithChildren> Children { get; set; }
}  

現在我需要一些方法來獲取List<ItemWithChildren> ,它將所有頂級Item對象及其子項放入Children屬性中。

請注意,嵌套不是一組設定的級別。

我希望有一個優雅的LINQ查詢可以工作。 到目前為止我只有這個......

var itemsWithChildren = items.Select(a => new ItemWithChildren{ Item = a });

不使用純Linq執行此任務更具可讀性,但Linq和循環的混合使用。

給出以下容器:

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

    public List<Node> Children { get; set; }
 }

然后,您可以使用以下代碼創建樹。

    var nodes = new List<Node>
    {
        new Node{ Id = 1 },
        new Node{ Id = 2 },
        new Node{ Id = 3, ParentId = 1 },
        new Node{ Id = 4, ParentId = 1 },
        new Node{ Id = 5, ParentId = 3 }
    };

    foreach (var item in nodes)
    {
        item.Children = nodes.Where(x => x.ParentId.HasValue && x.ParentId == item.Id).ToList();
    }

    var tree = nodes.Where(x => !x.ParentId.HasValue).ToList();

這將處理任何級別的深度並返回正確的樹。


給定以下打印樹的方法:

private void PrintTree(IEnumerable<Node> nodes, int indent = 0)
{
    foreach(var root in nodes)
    {
        Console.WriteLine(string.Format("{0}{1}", new String('-', indent), root.Id));
        PrintTree(root.Children, indent + 1);
    }
}

此調用的輸出是:

1
-3
--5
-4
2

但是,如果您想使用純Linq,可以執行以下操作,但對我來說,更難以閱讀:

       var tree = nodes.Select(item =>
        {
            item.Children = nodes.Where(child => child.ParentId.HasValue && child.ParentId == item.Id).ToList();
            return item;
        })
        .Where(item => !item.ParentId.HasValue)
        .ToList();

這可能有幫助嗎?

var itemsWithChildren = items.Select(a => new ItemWithChildren{ 
                                         Item = a,
                                         Children = items.Where(b => b.ParentId==a.Id)
                                                         .ToList()
                                    });

然后更新模型以實​​現它

  public string Name { get; set; }
    [DisplayName("Parent Category")]
    public virtual Guid? CategoryUID { get; set; }
    public virtual ICollection<Category> Categories { get; set; }

我認為你需要分兩步完成......我已經測試過它肯定有效......

        var items = new List<Item>();
        items.Add(new Item { Id = 1, ParentId = null });
        items.Add(new Item { Id = 2, ParentId = 1 });
        items.Add(new Item { Id = 3, ParentId = 1 });
        items.Add(new Item { Id = 4, ParentId = 3 });
        items.Add(new Item { Id = 5, ParentId = 3 });

        var itemsWithChildren = items.Select(a =>
            new ItemWithChildren { Item = a }).ToList();

        itemsWithChildren.ForEach(a =>
                a.Children = itemsWithChildren.Where(b => 
                    b.Item.ParentId == a.Item.Id).ToList());

        var root = itemsWithChildren.Single(a => !a.Item.ParentId.HasValue);

        Console.WriteLine(root.Item.Id);
        Console.WriteLine(root.Children.Count);
        Console.WriteLine(root.Children[0].Children.Count);
        Console.WriteLine(root.Children[1].Children.Count);

輸出...

1 2 0 2

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM