C# 基于Linq c的多级父子关系排序#

C# 基于Linq c的多级父子关系排序#,c#,asp.net,linq,list,guid,C#,Asp.net,Linq,List,Guid,我有一个列表,我需要将它排序到这个层次结构 { Id=1, ParentId = null, Name = "Item1", Type="0"} { Id=2, ParentId = 1, Name = "ItemChild1", Type="1"} { Id=3, ParentId = 1, Name = "ItemChild2", Type="1"} { Id=4, ParentId = 3, Name = "ItemGrandChild1", Type="2"}

我有一个列表,我需要将它排序到这个层次结构

{ Id=1, ParentId = null, Name = "Item1", Type="0"}
   { Id=2, ParentId = 1, Name = "ItemChild1", Type="1"}
   { Id=3, ParentId = 1, Name = "ItemChild2", Type="1"}
        { Id=4, ParentId = 3, Name = "ItemGrandChild1", Type="2"}
   { Id=5, **ParentId = 1**, Name = "ItemGrandChild2", Type="2"}

{ Id=6, ParentId = null, Name = "Item7", Type="0"}
...
与正常的父子关系不同,这里

类型2的项可以是类型1或类型0的子项

所有Id都是GUID

我见过may使用Linq在子-父排序上堆叠答案。但我的情况不同。
使用Linq的任何优雅方法?

创建查找以快速查找子项并将其投影到父集合。在我看来,这根本不取决于您的孩子是否有不同的类型,只要他们知道哪个元素是他们的父元素

public class TreeItem
{
    public int Id { get; set; }
    public int? ParentId { get; set; }
    public IEnumerable<TreeItem> Children { get; set; }

    public void PrintAllChildren()
    { 
        this.PrintAllChildren(0);
    }

    private void PrintAllChildren(int indent)
    {
        Debug.WriteLine("{1}Item id: {0}", this.Id, string.Concat(Enumerable.Repeat<int>(0, indent).Select(i => " ")));
        if (this.Children != null)
            foreach (var item in this.Children)
                item.PrintAllChildren(indent + 1);
    }
}

public static class TreeItemExtension
{
    public static IEnumerable<TreeItem> GetAsTree(this IEnumerable<TreeItem> data)
    {
        var lookup = data.ToLookup(i => i.ParentId);
        return lookup[null].Select(i => {
            i.FillChildren(lookup);
            return i;
        });
    }
    private static TreeItem FillChildren(this TreeItem item, ILookup<int?, TreeItem> lookup)
    {
        item.Children = lookup[item.Id].Select(i => i.FillChildren(lookup));
        return item;
    }
}
公共类树项
{
公共int Id{get;set;}
public int?ParentId{get;set;}
公共IEnumerable子项{get;set;}
public void printalchildren()
{ 
这是printalchildren(0);
}
私有void printalchildren(int缩进)
{
Debug.WriteLine(“{1}项id:{0}”,this.id,string.Concat(Enumerable.Repeat(0,缩进)。Select(i=>”);
if(this.Children!=null)
foreach(此.Children中的变量项)
项目.打印所有子项(缩进+1);
}
}
公共静态类树扩展
{
公共静态IEnumerable GetAsTree(此IEnumerable数据)
{
var lookup=data.ToLookup(i=>i.ParentId);
返回查找[null]。选择(i=>{
i、 填充子项(查找);
返回i;
});
}
私有静态TreeItem FillChildren(此TreeItem项,ILookup查找)
{
item.Children=lookup[item.Id]。选择(i=>i.FillChildren(lookup));
退货项目;
}
}

如果我是你,我会放弃尝试使用linq或sql对其进行排序。抽象可能会有帮助,但在这样复杂的情况下,它们只会妨碍您

如果您只编写自己的分类器,将节省大量时间

class MyCompare : IComparer<MyObject>
{
  public int Compare(x1, x2)
  {
      if (x1.parent == parent1 && x2.parent == parent2)
        return 1;
      if (x1.parent == x2.parent)
        return 0;
      //ect 
  }
}
List<MyObject> list = GetWeirdObjects();
list.Sort(new MyCompare());
class MyCompare:IComparer
{
公共整数比较(x1,x2)
{
如果(x1.parent==parent1&&x2.parent==parent2)
返回1;
如果(x1.parent==x2.parent)
返回0;
//ect
}
}
List List=GetWeirdObjects();
list.Sort(新的MyCompare());