2009-11-08 7 views
5

Digamos que tengo un objeto:3 elementos antiguos de la lista <> en C#

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

continuación, vamos a decir que tengo una lista con 20 diferentes elementos.

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" } 
} 

¿Cómo puedo eliminar los 3 elementos más antiguos?

stuff.RemoveAll(item => ???) 
+0

Si repite la lista para eliminar elementos, asegúrese de usar un para y no un foreeach. – jim

+0

Si "más antiguo" es para "primero en entrar", la solución más simple debe ser un enfoque de "primero en entrar, primero en salir": use una 'Cola '. –

+0

Excelente pregunta, fácil de entender el caso de uso, y me ha resultado realmente fácil para el lector encontrar la respuesta correcta. Gracias por preguntar como lo hiciste. – joelc

Respuesta

8

Si sólo necesita para enumerar los artículos, esto va a funcionar:

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

Si realmente lo quiere en forma de lista tendrá que llamar al .ToList() después:

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

no elimina los artículos, simplemente se salta y ¿qué hace con el valor devuelto? –

+0

Probablemente quiera hacer un .ToList() después de él. – Dykam

+1

No elimina los elementos de la lista fuente, pero el OP podría asignar el valor de retorno a otra cosa, p. llama a ToList y luego vuelve a asignarle la variable 'stuff'. –

3

Si la lista se ordena simplemente podría utilizar el RemoveRange método:

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

se debe pedir primero, luego eliminamos los últimos 3 –

1
const int cToRemove = 3; 

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

Si usted está dispuesto a sustituir la lista por uno nuevo, puede probar esto:

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

Por otro lado, si necesita stuff seguir siendo la misma instancia exacta List<T>, usted podría solucionar el problema y luego eliminar una serie por el índice:

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

Todas las otras respuestas hasta el momento se han basado en la clasificación de la lista, que es un O (n log n) la operación si no lo tiene ordenado

Aquí hay una solución que es O (n) aunque con un factor constante horrible. Utiliza MinBy desde MoreLINQ - podría reescribirlo fácilmente en su propio código si fuera necesario, e incluso hacer que devuelva el índice directamente en lugar del valor (y use RemoveAt en lugar de 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); 
} 

ciertamente se podría escribir esto de manera más eficiente para encontrar los tres elementos más antiguos de una sola pasada de la lista - pero el código sería mucho más complicado, dando lugar a más posibilidades de errores. Lo anterior debe funcionar bien en O (n), incluso si le falta elegancia cuando lo piensa yendo a través de la lista 6 veces :)

Cuestiones relacionadas