简体   繁体   English

从C#中的List <>中删除3个最旧的元素

[英]Remove 3 oldest elements from a List<> in C#

Let's say I have an object: 假设我有一个对象:

public class CustomObj
{
    DateTime Date { get; set; }
    String Name { get; set; }
}

Then let's say I have a List with 20 various elements. 然后,假设我有一个包含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" }
}

How can I remove the 3 oldest elements? 如何删除3个最古老的元素?

stuff.RemoveAll(item => ???)

If you only need to enumerate the items, this will work: 如果您只需要枚举项目,这将有效:

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

If you actually want it in list form you will have to call .ToList() afterwards: 如果你真的想要它以列表形式,你将不得不调用.ToList()之后:

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

If you're willing to replace the list with a new one, you could try this: 如果您愿意用新的列表替换列表,可以尝试这样做:

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

On the other hand, if you need stuff to remain the same exact List<T> instance, you could sort it and then remove a range by index: 另一方面,如果您需要的stuff保持相同的List<T>实例,您可以对其进行排序,然后按索引删除范围:

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

If your list is ordered you could simply use the RemoveRange method: 如果您的列表是订购的,您只需使用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);

All the other answers so far have relied on sorting the list, which is an O(n log n) operation if you don't already have it sorted. 到目前为止,所有其他答案都依赖于对列表进行排序,如果您尚未对其进行排序,则该操作是O(n log n)操作。

Here's a solution which is O(n) albeit it with a horrible constant factor. 这是一个O(n)的解决方案,尽管它具有可怕的常数因子。 It uses MinBy from MoreLINQ - you could easily rewrite that in your own code if you need to, and even make it return the index directly instead of the value (and use RemoveAt instead of Remove ). 它使用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);
}

You could certainly write this more efficiently to find the oldest three elements in a single pass of the list - but the code would be significantly more complicated, leading to more chances for errors. 你当然可以更有效地编写这个来在列表的单个传递中找到最旧的三个元素 - 但代码会更加复杂,导致更多的错误机会。 The above should work fine in O(n), even if it's lacking in elegance when you think of it going through the list 6 times :) 上面应该可以在O(n)中正常工作,即使它在你认为它通过列表6次时缺乏优雅:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM