[英]Remove 3 oldest elements from a List<> in C#
假設我有一個對象:
public class CustomObj
{
DateTime Date { get; set; }
String Name { get; set; }
}
然后,假設我有一個包含20種不同元素的列表。
var stuff = new List<CustomObj>
{
{ Date = DateTime.Now, Name = "Joe" },
{ Date = DateTime.Now.AddDays(1), Name = "Joe2" },
{ Date = DateTime.Now.AddDays(2), Name = "Joe3" },
{ Date = DateTime.Now.AddDays(3), Name = "Joe4" },
{ Date = DateTime.Now.AddDays(4), Name = "Joe5" },
{ Date = DateTime.Now.AddDays(5), Name = "Joe6" },
{ Date = DateTime.Now.AddDays(6), Name = "Joe7" },
{ Date = DateTime.Now.AddDays(7), Name = "Joe8" },
{ Date = DateTime.Now.AddDays(8), Name = "Joe9" },
{ Date = DateTime.Now.AddDays(9), Name = "Joe10" },
{ Date = DateTime.Now.AddDays(10), Name = "Joe11" }
}
如何刪除3個最古老的元素?
stuff.RemoveAll(item => ???)
如果您只需要枚舉項目,這將有效:
stuff.OrderBy(item => item.Date).Skip(3);
如果你真的想要它以列表形式,你將不得不調用.ToList()
之后:
stuff = stuff.OrderBy(item => item.Date).Skip(3).ToList();
如果您願意用新的列表替換列表,可以嘗試這樣做:
stuff = stuff.OrderBy( c => c.Date).Skip(3).ToList();
另一方面,如果您需要的stuff
保持相同的List<T>
實例,您可以對其進行排序,然后按索引刪除范圍:
stuff.Sort(...);
stuff.RemoveRange(0, 3);
如果您的列表是訂購的,您只需使用RemoveRange
方法:
int n = 3;
stuff.RemoveRange(stuff.Count - n, n);
const int cToRemove = 3;
var top3 = (from c in stuff
orderby c.Date ascending
select c).Take(cToRemove);
到目前為止,所有其他答案都依賴於對列表進行排序,如果您尚未對其進行排序,則該操作是O(n log n)操作。
這是一個O(n)的解決方案,盡管它具有可怕的常數因子。 它使用MinBy
的MinBy - 如果需要,您可以在自己的代碼中輕松地重寫它,甚至使它直接返回索引而不是值(並使用RemoveAt
而不是Remove
)。
// The list.Count part is in case the list starts off with
// fewer than 3 elements
for (int i = 0; i < 3 && list.Count > 0; i++)
{
var oldest = list.MinBy(x => x.Date);
list.Remove(oldest);
}
你當然可以更有效地編寫這個來在列表的單個傳遞中找到最舊的三個元素 - 但代碼會更加復雜,導致更多的錯誤機會。 上面應該可以在O(n)中正常工作,即使它在你認為它通過列表6次時缺乏優雅:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.