【问题标题】:Flatten a hierarchy as specifically sorted list将层次结构展平为专门排序的列表
【发布时间】:2015-04-07 05:46:23
【问题描述】:

我有一个简单的人员层次结构(EntityFramework Codefirst)。

public class Person
{
    [Key]
    public int Id { get; set; }

    public int? ParentId { get; set; }

    [Required]
    public string Name { get; set; }

    // Navigation

    [ForeignKey("ParentId")]
    public virtual Person Parent { get; set; }

    public virtual ICollection<Person> Children { get; set; }
}

我的目标:

我需要一个创建List&lt;Person&gt; 的方法,它 (1) 由父母聚集和 (2) 按名称按字母顺序排序在每个级别

示例输出:

  • 阿尔弗雷德
  • 本(阿尔弗雷德的儿子)
  • 马里昂(阿尔弗雷德的女儿)
  • 拉尔夫(阿尔弗雷德的儿子)
  • 克里斯汀
  • Ally(克里斯汀的女儿)
  • 戴夫
  • 多丽丝
  • 詹姆斯(多丽丝的儿子)
  • 克拉斯(多丽丝的儿子)

Alfred、Christine、Dave 和 Doris 都是父母。它们按字母顺序排序。他们都有孩子(戴夫除外)。孩子也按字母顺序排序(在列表中,他们与父母一起“分组”)。 “儿子”和“女儿”对你们来说只是 cmets(我在结果列表中不需要这个)。

我可以使用嵌套循环轻松创建这种列表。但我确信这不会非常有效或优雅。但也许我错了。

你们有没有人有好的想法/建议(可能是 LINQ)?谢谢!!

哦,我应该提一下,层次结构只有 2 级。所以,只有父母和孩子(但没有孙子)。

【问题讨论】:

    标签: c# linq ef-code-first


    【解决方案1】:
    var sortedPeople = 
        from p in people
        orderby (p.Parent == null ? p.Name : p.Parent.Name),
          p.Parent == null ? 1 : 2, // this ensures parents appear before children
          p.Name
        select p;
    

    【讨论】:

    • 这正是我想要的!谢谢,克林特!
    • 这列出了孩子吗?
    • 可以,只要他们在“人”中
    【解决方案2】:

    这行得通吗?

    List<Person> sortPeople(List<Person> people)
    {
        List<Person> result = new List<Person>();
    
        foreach (Person p in people.OrderBy(_ => _.Name).ToList())
        {
            result.Add(p);
            result.AddRange(p.Children.OrderBy(_ => _.Name).ToList());
        }
    
        return result;
    }
    

    【讨论】:

    • 您好,artm,感谢您的回答。这就是我会想出的。干净整洁。但我更喜欢克林特的回答。但再次感谢!
    【解决方案3】:

    这只有在有两个级别时才有效,我不知道这如何转换为 SQL:

    var parents = people.Select(person=>person.Parent == null);
    var parentsWithChildrenGrouped = 
        parents
        .SelectMany(parent=>parent.Children.Select(child=>new {Parent = parent, Child = child, Out = child}))
        .Union(parents.Select(parent => new {Parent = parent, Child = null, Out = parent}))
        .OrderBy(x=>x.Parent).ThenBy(x=>x.Child)
        .Select(x=>x.Out);
    

    此查询首先创建列表,其中每个项目都有子项和父项。然后它首先根据父级排序,然后按子级排序。然后是第三个“out”属性,它定义了该行的用途。

    我知道这可以很容易地转换为有效的 SQL,但我不确定 EF 将如何处理它。

    【讨论】:

    • 嗨 Euphoric,到目前为止我还没有尝试过你的解决方案。我第一次看到克林特的回答,就知道这是我一直在寻找的那种代码。不过你的看起来也很棒。非常感谢您的努力!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多