2009-11-08 45 views
5

刪除最舊的3個元素比方說,我有一個對象:從列表<>在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 => ???) 
+0

如果你迭代列表來刪除項目,確保你使用for和不是一個foreeach。 – jim 2009-11-08 07:49:16

+0

如果「最老」是「先入」,最簡單的解決方案應該是「先進先出」方法:使用「隊列」。 – 2013-06-11 14:35:51

+0

優秀的問題,易於理解的用例,使我作爲讀者很容易找到正確的答案。感謝您問的問題。 – joelc 2015-11-01 21:42:17

回答

8

如果你只需要列舉的項目,這將工作:

stuff.OrderBy(item => item.Date).Skip(3); 

如果你真的想以列表的形式,你將不得不打電話.ToList()事後:

stuff = stuff.OrderBy(item => item.Date).Skip(3).ToList(); 
+1

它不會刪除項目,只是跳過它並做什麼與返回值? – 2009-11-08 08:01:53

+0

他可能想在它之後做一個.ToList()。 – Dykam 2009-11-08 08:12:06

+1

它不會從源列表中刪除項目,但OP可以將返回值分配給其他值,例如,調用ToList,然後重新分配給'stuff'變量。 – 2009-11-08 08:12:08

3

如果你的列表進行排序,你可以簡單地使用RemoveRange方法:

int n = 3; 
stuff.RemoveRange(stuff.Count - n, n); 
+3

它應該先訂購,然後我們刪除最後3 – 2009-11-08 07:44:25

1
const int cToRemove = 3; 

var top3 = (from c in stuff 
     orderby c.Date ascending 
     select c).Take(cToRemove); 
4

如果你願意用一個新的來代替列表,你可以試試這個:

stuff = stuff.OrderBy(c => c.Date).Skip(3).ToList(); 

在另一方面,如果你需要stuff保持完全相同的List<T>例如,你可以對它進行排序,然後通過索引中刪除一個範圍:

stuff.Sort(...); 
stuff.RemoveRange(0, 3); 
1

其他所有的答案至今依靠排序列表,這是一個爲O​​(n log n)的操作,如果你不已經擁有了它排序。

這是一個解決方案,它是O(n)儘管它有一個可怕的常數因子。它使用MinByMoreLINQ - 如果需要,您可以輕鬆地在自己的代碼中重寫該代碼,甚至可以直接返回索引而不是值(並使用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次:)