簡體   English   中英

從C#中的List <>中刪除3個最舊的元素

[英]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)的解決方案,盡管它具有可怕的常數因子。 它使用MinByMinBy - 如果需要,您可以在自己的代碼中輕松地重寫它,甚至使它直接返回索引而不是值(並使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM