C# - LINQ将项目展开为分层集合

时间:2015-09-16 21:10:29

标签: c# linq

是否可以使用LINQ语句将展平的集合转换为分层集合?我用常规'foreach'(使用了很多行代码)完成了这个,但是我希望有一些LINQ方法,以使它运行得更快。我的班级看起来像这样:

public class Register
{
    public Guid ID { get; set; }
    public Guid IDParent { get; set; }
    public string Caption { get; set; }
    public ObservableCollection<Register> Children { get; set; }
}

扁平化的项目将被添加到这样的集合中,根项目具有IDParent = new Guid(),一个'零' - Guid:

public void InitializeCollection()
{
    ObservableCollection<Register> collectionFlat = new ObservableCollection<Register>();

    // 0 level, can be found by IDParent = {00000000-0000-0000-0000-000000000000}
    collectionFlat.Add(new Register()
    {
        Caption = "A",
        ID = Guid.Parse("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"),
        IDParent = Guid.Parse("00000000-0000-0000-0000-000000000000"),
        Children = new ObservableCollection<Register>(),
    });

    // 1 level
    collectionFlat.Add(new Register()
    {
        Caption = "A-1",
        ID = Guid.Parse("A1A1A1A1-A1A1-A1A1-A1A1-A1A1A1A1A1A1"),
        IDParent = Guid.Parse("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"),
        Children = new ObservableCollection<Register>(),
    });

    // 1 level
    collectionFlat.Add(new Register()
    {
        Caption = "A-2",
        ID = Guid.Parse("A2A2A2A2-A2A2-A2A2-A2A2-A2A2A2A2A2A2"),
        IDParent = Guid.Parse("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"),
        Children = new ObservableCollection<Register>(),
    });

    // 2 level
    collectionFlat.Add(new Register()
    {
        Caption = "A-2-B",
        ID = Guid.Parse("A2B0A2B0-A2B0-A2B0-A2B0-A2B0A2B0A2B0"),
        IDParent = Guid.Parse("A2A2A2A2-A2A2-A2A2-A2A2-A2A2A2A2A2A2"),
        Children = new ObservableCollection<Register>(),
    });
}

给出了这棵树:

  • 'A'
  • - 'A-1'
  • - 'A-2'
  • - 'A-2-B'

2 个答案:

答案 0 :(得分:1)

尝试按IDParent对集合进行分组,然后创建一个字典,其中key是group的IDParent值,value是当前组中的项目列表。

所以,你可以在你的等级上下来但不能上去。

例如,对于ID = Guid.Parse(&#34; 00000000-0000-0000-0000-000000000000&#34;)的项目,您需要查看YourDictionary [项目.ID ]你会得到它的所有后代。

答案 1 :(得分:1)

将我的解决方案从this answer重用到一个非常相似的问题,您可以这样做:

// create a mapping: id => obj
var mapping = collectionFlat.ToDictionary(x => x.ID);

// target collection
var output = new ObservableCollection<Register>();

foreach (var obj in mapping.Values)
{
    // if the parent id is an empty Guid, this is a top-level entry; otherwise
    // get the parent element from the mapping, and add to its children collection
    if (obj.IDParent == Guid.Empty)
        output.Add(x);
    else
        mapping[obj.IDParent].Children.Add(obj);
}