简体   繁体   中英

c# hierarchy list (tree) to flatt list

I have the following class:

public class Item
{

    public Item()
    {
        this.Items = new List<Item>();
    }

    public string Id { get; set; }
    public string ParentId { get; set; }
    public string Name { get; set; }
    public DateTime Created { get; set; }
    public string Content { get; set; }
    public string UserId { get; set; }
    List<Item> Children { get; set; }
}

This class will provide a tree hierarchical structure with N deep levels (parent - children)

So basically when I get the hierarchy as a list:

List<Item> items = JsonConvert.DeserializeObject<List<Item>>("json in here")

The result will be similar to this: the deepness can be X levels. There can be one or more parents (ParentId = null is top level)

  • Parent (Id:1, ParentId: null)
    • Child (Id: 1.1, ParentId: 1)
      • Child (Id: 1.1.1, ParentId: 1.1)
    • Child (Id: 1.2, ParentId: 1)
      • Child (Id: 1.2.1, ParentId: 1.2)
      • Child (Id: 1.2.2, ParentId: 1.2)
    • Child (Id: 1.3, ParentId: 1)
  • Parent (Id:2, ParentId: null)
    • Child (Id: 2.1, ParentId: 2)
      • Child (Id: 2.1.1, ParentId: 2.1)
    • Child (Id: 2.2, ParentId: 2)
      • Child (Id: 2.2.1, ParentId: 2.2)
      • Child (Id: 2.2.2, ParentId: 2.2)
    • Child (Id: 2.3, ParentId: 2)
  • Parent (Id:3, ParentId: null)

Now, I need to save this hierarchy into a database table.

My question how can I flatten this hierarchy to a List<Item> ?

EDIT:

The Id and ParentId are Guids.

You can add a function to the Item class like this:

public IEnumerable<Item> GetItems()
{
    var result = Children.SelectMany(i => i.GetItems()).ToList();

    result.Add(this);

    return result;
}

Then call it

var allItems = myRootItem.GetItems();

Here are a couple of choices:

public IEnumerable<Item> GetItems()
{
    return
        new [] { this }
            .Concat(this.Children.SelectMany(i => i.GetItems()));
}

public IEnumerable<Item> GetItems()
{
    yield return this;
    foreach (var descendent in this.Children.SelectMany(i => i.GetItems()))
    {
        yield return descendent;
    }
}

This Recursive function might help in order to Save your data in a flat structure :

class Test
{
    List<Item> Items = new List<Item>();
    List<Item> GetList()
    {
        return getList_Rec(this.Items);
    }

    private List<Item> getList_Rec(List<Item> items)
    {
        var result = new List<Item>();
        result.AddRange(items);
        items.ForEach(x => result.AddRange(x.Children));
        return result;
    }
}

If you expose Children so it isn't private you can do this:

public IEnumerable<Item> GetItems(IEnumerable<Item> items)
{
    foreach(var item in items)
    {
        yield return item;
        foreach(var child in GetItems(item.Children))
        {
            yield return child;
        }
     }
 }

Then feed in your enumeration of parents and get a flat list.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM