Linq集团由父母的财产秩序由孩子

基本上我想要做的是获得由Parent.type父组分类,其中他们的Child.type具有由child.Date排序的状态'y'

作为一个例子,我创建了这些类:

public class Collection
{
    public IEnumerable<Parent> Parents { get; set; }
    public int Id { get; set; }
}

public class Parent
{
    public int Id { get; set; }
    public Type type { get; set; }       
    public IEnumerable<Child> Children { get; set; }
}

public class Child
{
    public int Id { get; set; }
    public Status Status { get; set; }
    public DateTime Date { get; set; }
}

public enum Type
{
    a,
    b
}

public enum Status
{
    x,
    y
}

我想要的是每个类型的父母名单,其中孩子的日期是最高的价值。

为了得到这个例子,我添加了一些测试数据:

Collection collection= new Collection
        {
            Id = 1,
            Parents = new List<Parent>
            {
                new Parent
                {
                    Id= 1,
                    type = Type.a,
                    Children = new List<Child>
                    {
                        new Child
                        {
                            Id = 1,
                            Status = Status.y,
                            Date = DateTime.Now.AddDays(-1)
                        },
                        new Child
                        {
                            Id = 2,
                            Status = Status.x,
                            Date = DateTime.Now.AddDays(-1)
                        }
                    }
                },
                new Parent
                {
                    Id= 2,
                    type = Type.b,
                    Children = new List<Child>
                    {
                        new Child
                        {
                            Id = 3,
                            Status = Status.y,
                            Date = DateTime.Now.AddDays(-2)
                        },
                        new Child
                        {
                            Id = 4,
                            Status = Status.x,
                            Date = DateTime.Now.AddDays(-2)
                        }
                    }
                },
                new Parent
                {
                    Id= 3,
                    type = Type.a,
                    Children = new List<Child>
                    {
                        new Child
                        {
                            Id = 5,
                            Status = Status.y,
                            Date = DateTime.Now.AddDays(-3)
                        }
                    }
                },
                new Parent
                {
                    Id= 4,
                    type = Type.b,
                    Children = new List<Child>
                    {
                        new Child
                        {
                            Id = 6,
                            Status = Status.y,
                            Date = DateTime.Now.AddDays(-3)
                        },
                        new Child
                        {
                            Id = 7,
                            Status = Status.y,
                            Date = DateTime.Now.AddDays(-4)
                        },
                        new Child
                        {
                            Id = 8,
                            Status = Status.x,
                            Date = DateTime.Now.AddDays(-4)
                        }
                    }
                },
            }
        };

选择的结果应该是包含2个父母的列表。 每种类型一个(a和b)。 这两个仍然包含他们所有的Child对象。

有没有简单的解决方案?

我尝试了这样的:

List<Parent> test = collection.Parents
                .GroupBy(m => m.type)
                .Select(
                m => m.OrderByDescending(
                    mm => mm.Children.Select(
                        r => r).OrderByDescending(
                            r => r.Date)).FirstOrDefault()).ToList();

但那并没有结束。

=====更新=====

感谢Enigmativity的例子,这个问题解决了。 我对linq查询做了一些修改,因为我使用的原始内容是由Entity Framework(6)提供的。 这对我来说意味着所选的Parent对象不包含任何Children,所以我必须选择一个新的对象类型(因为我们不能实例化由Entity Framework模型提供的类型的新对象)。 此外,我的父母还在另一个IEnumerable中,所以我不得不在父母身上使用SelectMany。

这导致了这样的事情:(但这不会与测试类一起工作)

var result =
    collection
        .SelectMany(c => c.Parents)
        .GroupBy(p => p.type)
        .SelectMany(gps =>
            gps
                .SelectMany(
                    gp => gp.Children.Where(c => c.Status == Status.y),
                    (gp, c) => new { gp, c })
                .OrderByDescending(gpc => gpc.c.Date)
                .Take(1)
                .Select(gpc => new ParentData {Id = gpc.gp.Id, Children= gpc.gp.Children}))
        .ToList();

如果我已经正确理解了您的要求,您希望按类型对所有父母进行分组,然后根据该父母中的所有孩子中具有最高日期的孩子,从每个分组中选择一个父母。

以下是我想到的:

var result =
    collection
        .Parents
        .GroupBy(p => p.type)
        .SelectMany(gps =>
            gps
                .SelectMany(
                    gp => gp.Children.Where(c => c.Status == Status.y),
                    (gp, c) => new { gp, c })
                .OrderByDescending(gpc => gpc.c.Date)
                .Take(1)
                .Select(gpc => gpc.gp))
        .ToList();

这给了我:


当父母是查询/预测正在被应用的时候,儿童不能真正被过滤,排序等。

你必须要么:

  • 打破关系并将项目投影到不同的数据结构(如字典或IGrouping ,其中父项是关键字,排序的子项是值)
  • 在不使用LINQ的情况下,必须对子进行Sort()或重新分配Children
  • 写多行lambda表达式,其中第二行是排序或分配子项的副作用(不推荐)
  • 就我个人而言,我认为只需将您需要的数据投影到简化的表示上比将整个层次结构保留下来更容易。


    我对这个问题的理解是,您需要创建一个按类型分组的父母列表,并为每个父类型汇总所有具有状态y的子项。

    为此,请注意,您不能通过父类型折叠列表并保留父结构(这意味着ID也必须被折叠,我只取第一个值,这取决于您选择不同的值)。 否则,这应该是您正在寻找的解决方案:

    var result = collection.Parents.GroupBy(c => c.type)
        .Select(g => new Parent
                     {
                         type = g.Key,      
                         Id = g.Select(p => p.Id).FirstOrDefault(),
                         Children = g.SelectMany(p => p.Children
                                  .Where(c => c.Status == Status.y)
                                  .OrderByDescending(c => c.Date)).ToList()                           
                     }).ToList();
    
    链接地址: http://www.djcxy.com/p/37655.html

    上一篇: Linq group by parent property order by child

    下一篇: Linq ordering both parent and child related entities