[英]Linq OrderBy Sub List
我試圖執行一個相當簡單的順序,但似乎正在努力如何去做。 舉個例子,我有這兩個類。
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
轉換為可空, Min()
將為空序列返回null,而具有空槽列表的Method
對象將被排序到開頭。
我想解釋為什么您在原始帖子中發布的嘗試無效:
var xyz = deliveryMethods
.OrderBy(x => x.Slots.OrderBy(y => y.ExpectedDeliveryDate.Year))
.ThenBy(x => x.Slots.OrderBy(y => y.ExpectedDeliveryDate.Month))
.ThenBy(x => x.Slots.OrderBy(y => y.ExpectedDeliveryDate.Date))
.ToList();
這是因為你的嵌套OrderBy
在s OrderBy
秒。
x.Slots.OrderBy(...)
生成一個IEnumerable<Slot>
,所以你基本上是在告訴它“將這些IEnumerable<Slot>
相互比較來決定交付方法的順序”。 但Linq不知道如何將IEnumerable<Slot>
與另一個進行比較並確定哪一個先於另一個( IEnumerable<Slot>
未實現IComparable<T>
),因此您收到錯誤。
正如另一位用戶所指出的那樣,答案就是給它一些可以比較的東西。 正如您后來澄清的那樣,這將是每種交付方式的最早時段:
var xyz = deliveryMethods
.OrderBy(x => x.Slots.Min(y => y.ExpectedDeliveryDate))
.ToList();
這將在假設每個傳遞方法至少有一個槽的情況下工作,但如果它們中的任何一個具有零槽(或者如果Slots
為空),則將拋出運行時異常。 我曾兩次問過你應該做些什么,我鼓勵你澄清一下。
一種可能的解決方案是僅包含具有插槽的交付方法:
var xyz = deliveryMethods
.Where(x => x.Slots != null && x.Slots.Any())
.OrderBy(x => x.Slots.Min(y => y.ExpectedDeliveryDate))
.ToList();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.