Linq OrderBy Sub List[英] Linq OrderBy Sub List

本文是小编为大家收集整理的关于Linq OrderBy Sub List的处理/解决方法,可以参考本文帮助大家快速定位并解决问题,中文翻译不准确的可切换到English标签页查看源文。

问题描述

我正在尝试执行一个相当简单的订单,但似乎在努力解决如何去做.以我有这两个类为例.

public class Method
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set; }

    public List<Slot> Slots { get; set; }
}

public class Slot
{
    public DateTime ExpectedDeliveryDate { get; set; }
}

使用下面的代码,我想按最便宜的选项订购,然后按最快的交货日期订购.

var methods = new List<Method>();

methods.Add(new Method { Id = 1, Name = "Standard", Price = 0M, Slots = new List<Slot> { new Slot { ExpectedDeliveryDate = DateTime.Now.AddDays(5).Date } } });
methods.Add(new Method { Id = 2, Name = "Super Fast Next Day", Price = 0M, Slots = new List<Slot> { new Slot { ExpectedDeliveryDate = DateTime.Now.AddDays(1).Date } } });

var b = methods.OrderBy(x => x.Price)
    .ThenBy(y => y.Slots.OrderBy(t => t.ExpectedDeliveryDate.Date)
        .ThenBy(t => t.ExpectedDeliveryDate.TimeOfDay))
            .ToList();

我在这里遇到的麻烦是我收到一个运行时错误,指出"至少一个对象必须实现 IComparable".

虽然我可以通过实现 IComparable 接口来解决这个问题,但我想知道是否可以这样做.我想好像我有这段代码(见下文)它工作正常.

var slots = new List<Slot>();

slots.Add(new Slot { ExpectedDeliveryDate = DateTime.Now.AddDays(5).Date });
slots.Add(new Slot { ExpectedDeliveryDate = DateTime.Now.AddDays(1).Date });
slots.Add(new Slot { ExpectedDeliveryDate = DateTime.Now.AddDays(3).Date });
slots.Add(new Slot { ExpectedDeliveryDate = DateTime.Now.Date });

var d = slots.OrderBy(x => x.ExpectedDeliveryDate);

干杯,DS.

对于上面示例中的 xyz 等变量的命名表示歉意 :) 可以复制和粘贴代码以方便操作.

编辑- 更新以简化代码示例.- 排序成功后的预期结果

Input
  ID     Name            Price    Slot
  1      Standard        0        DateTime.Now.AddDays(5).Date
  2      Super Fast      0        DateTime.Now.Date

Output
  2      Super Fast      0        DateTime.Now.Date  
  1      Standard        0        DateTime.Now.AddDays(5).Date

所以我的超快速选项应该是首选,因为它是最便宜的,当然还有最快的交货日期.

推荐答案

你可以使用 Enumerable.Min() 来挑出日期最早的槽,像这样:

        var query = deliveryMethods
            .OrderBy(x => x.Slots.Min(s => s.ExpectedDeliveryDate).Year)
            .ThenBy(x => x.Slots.Min(s => s.ExpectedDeliveryDate).Month)
            .ThenBy(x => x.Slots.Min(s => s.ExpectedDeliveryDate).Date)
            .ToList();

或者,只是

        var query = deliveryMethods
            .OrderBy(x => x.Slots.Min(s => s.ExpectedDeliveryDate.Date))
            .ToList();

请注意,当输入序列为空并且被最小化的类型是值类型时,Min() 会抛出异常.如果你想避免异常,你可以这样做:

        var query2 = deliveryMethods
            .OrderBy(x => x.Slots.Min(s => (DateTime?)(s.ExpectedDeliveryDate.Date)))
            .ToList();

通过将 DateTime 转换为 nullable,Min() 将为空序列返回 null,并且具有空槽列表的 Method 对象将被排序到开头.

本文地址:https://www.itbaoku.cn/post/1556840.html

问题描述

I am trying to perform a fairly simple order by but seem to be struggling on how to go about doing it. Take for instance I have these two classes.

public class Method
{
    public int Id { get; set; }

    public string Name { get; set; }

    public decimal Price { get; set; }

    public List<Slot> Slots { get; set; }
}

public class Slot
{
    public DateTime ExpectedDeliveryDate { get; set; }
}

Using the code below I want to order by the cheapest option and then by the quickest delivery date.

var methods = new List<Method>();

methods.Add(new Method { Id = 1, Name = "Standard", Price = 0M, Slots = new List<Slot> { new Slot { ExpectedDeliveryDate = DateTime.Now.AddDays(5).Date } } });
methods.Add(new Method { Id = 2, Name = "Super Fast Next Day", Price = 0M, Slots = new List<Slot> { new Slot { ExpectedDeliveryDate = DateTime.Now.AddDays(1).Date } } });

var b = methods.OrderBy(x => x.Price)
    .ThenBy(y => y.Slots.OrderBy(t => t.ExpectedDeliveryDate.Date)
        .ThenBy(t => t.ExpectedDeliveryDate.TimeOfDay))
            .ToList();

The trouble I am getting here is that I am getting a runtime error stating "At least one object must implement IComparable".

Although I can fix this by implementing the IComparable interface, I was wondering if it was possible to do this. I imagine there is as if I had this code (see below) it works fine.

var slots = new List<Slot>();

slots.Add(new Slot { ExpectedDeliveryDate = DateTime.Now.AddDays(5).Date });
slots.Add(new Slot { ExpectedDeliveryDate = DateTime.Now.AddDays(1).Date });
slots.Add(new Slot { ExpectedDeliveryDate = DateTime.Now.AddDays(3).Date });
slots.Add(new Slot { ExpectedDeliveryDate = DateTime.Now.Date });

var d = slots.OrderBy(x => x.ExpectedDeliveryDate);

Cheers, DS.

Apologies for the naming of variables such as xyz in example above :) Code can be copied and pasted for manipulation pleasure.

EDIT - Updated to simplify code example. - Expectation of result would be after successful sorting

Input
  ID     Name            Price    Slot
  1      Standard        0        DateTime.Now.AddDays(5).Date
  2      Super Fast      0        DateTime.Now.Date

Output
  2      Super Fast      0        DateTime.Now.Date  
  1      Standard        0        DateTime.Now.AddDays(5).Date

So my super fast option should be top due to it being the cheapest and of course has the quickest delivery date.

推荐答案

You can use Enumerable.Min() to pick out the slot with the earliest date, like so:

        var query = deliveryMethods
            .OrderBy(x => x.Slots.Min(s => s.ExpectedDeliveryDate).Year)
            .ThenBy(x => x.Slots.Min(s => s.ExpectedDeliveryDate).Month)
            .ThenBy(x => x.Slots.Min(s => s.ExpectedDeliveryDate).Date)
            .ToList();

Or, just

        var query = deliveryMethods
            .OrderBy(x => x.Slots.Min(s => s.ExpectedDeliveryDate.Date))
            .ToList();

Do be aware that Min() will throw an exception when the input sequence is empty and the type being minimized is a value type. If you want to avoid the exception, you could do this:

        var query2 = deliveryMethods
            .OrderBy(x => x.Slots.Min(s => (DateTime?)(s.ExpectedDeliveryDate.Date)))
            .ToList();

By converting the DateTime to a nullable, Min() will return a null for an empty sequence, and Method objects with empty slot list will get sorted to the beginning.