¿Cómo eliminar un elemento de la lista en C #?

192

Tengo una lista almacenada en la lista de resultados de la siguiente manera:

var resultlist = results.ToList();

Se parece a esto:

ID FirstName  LastName
-- ---------  --------
1  Bill       Smith
2  John       Wilson
3  Doug       Berg

¿Cómo elimino el ID 2 de la lista?

Nate Pet
fuente

Respuestas:

368

List<T> tiene dos métodos que puedes usar.

RemoveAt (int index) se puede usar si conoce el índice del elemento. Por ejemplo:

resultlist.RemoveAt(1);

O puede usar Eliminar (elemento T) :

var itemToRemove = resultlist.Single(r => r.Id == 2);
resultList.Remove(itemToRemove);

Cuando no esté seguro de que el elemento realmente exista, puede usar SingleOrDefault . SingleOrDefaultregresará nullsi no hay ningún artículo ( Singlearrojará una excepción cuando no pueda encontrar el artículo). Ambos se lanzarán cuando haya un valor duplicado (dos elementos con el mismo id).

var itemToRemove = resultlist.SingleOrDefault(r => r.Id == 2);
if (itemToRemove != null)
    resultList.Remove(itemToRemove);
Wouter de Kort
fuente
55
bueno, tal vezvar itemsToRemove = resultlist.Where(r => r.Id == 2); foreach (var itemToRemove in ItemsToRemove) resultList.Remove(itemToRemove);
Vlad
1
¿No debería ser esto resultlist.Items.RemoveAt(1);?
DreamTeK
50

Respuesta corta:
Eliminar (de la lista results)

results.RemoveAll(r => r.ID == 2);eliminará el elemento con ID 2 en results(en su lugar).

Filtro (sin eliminar de la lista original results):

var filtered = result.Where(f => f.ID != 2);devuelve todos los artículos excepto el que tiene ID 2

Respuesta detallada:

Creo que .RemoveAll()es muy flexible, porque puede tener una lista de ID de elementos que desea eliminar; tenga en cuenta el siguiente ejemplo.

Si usted tiene:

class myClass {
    public int ID; public string FirstName; public string LastName;
}

y asignó algunos valores de la resultssiguiente manera:

var results=new List<myClass> {
    new myClass()  { ID=1, FirstName="Bill", LastName="Smith" },
    new myClass()  { ID=2, FirstName="John", LastName="Wilson" },
    new myClass()  { ID=3, FirstName="Doug", LastName="Berg" },
    new myClass()  { ID=4, FirstName="Bill", LastName="Wilson" },
};

Luego puede definir una lista de ID para eliminar:

var removeList = new List<int>() { 2, 3 };

Y simplemente use esto para eliminarlos:

results.RemoveAll(r => removeList.Any(a => a==r.ID));

Será eliminar los elementos 2 y 3 y mantener los elementos 1 y 4 - tal como se especifica por el removeList. Tenga en cuenta que esto sucede en su lugar, por lo que no se requiere asignación adicional.

Por supuesto, también puede usarlo en elementos individuales como:

results.RemoveAll(r => r.ID==4);

donde eliminará Bill con ID 4 en nuestro ejemplo.


DotNetFiddle: ejecute la demostración

Mate
fuente
45
resultList = results.Where(x=>x.Id != 2).ToList();

Hay un pequeño ayudante de Linq que me gusta que es fácil de implementar y puede hacer que las consultas con condiciones "donde no" sean un poco más fáciles de leer:

public static IEnumerable<T> ExceptWhere<T>(this IEnumerable<T> source, Predicate<T> predicate)
{
    return source.Where(x=>!predicate(x));
}

//usage in above situation
resultList = results.ExceptWhere(x=>x.Id == 2).ToList();
KeithS
fuente
1
Otro enfoque similar (que usa un predicado) es usar List.FindIndex/ List.RemoteAt(que tiene la característica "agradable" o "no tan agradable" de ser una operación mutante).
Es cierto, pero tenga cuidado al decir que la operación de List está mutando. List utiliza una matriz detrás de escena, y puede recrear su matriz con una capacidad menor o mayor cuando lo considere necesario. Por lo general , la eliminación es una mutación in situ de la matriz existente.
KeithS
Esta caja fuerte hilo isnt, y por su sencillez sólo se puede utilizar SingleOrDefault, doesnt necesidad de estar contenida en un método estático
Nadie dijo que fuera seguro para subprocesos (y si depende de lo que se supone que deben estar haciendo los subprocesos; de hecho, puede ser preferible dar una construcción en memoria diferente a un subproceso de trabajo en lugar de permitir que todos trabajen en una colección simultánea ), y el OP quiere todos los registros excepto el que coincida con el predicado, por lo que SingleOrDefault devolvería exactamente lo que no quiere. El "método estático" es, de hecho, un método de extensión, como la mayoría de Linq, y funciona siempre que lo que no desea (un elemento o muchos) es más fácil de definir que lo que hace.
KeithS
5

Hay otro enfoque. Utiliza List.FindIndexy List.RemoveAt.

Si bien probablemente usaría la solución presentada por KeithS (solo la simple Where/ ToList), este enfoque difiere en que muta el objeto de lista original. Esto puede ser una buena (o mala) "característica" dependiendo de las expectativas.

En cualquier caso, FindIndex(junto con una protección) garantiza RemoveAtque será correcto si hay huecos en las ID o si el orden es incorrecto, etc., y el uso de RemoveAt(vs Remove) evita una segunda búsqueda O (n) en la lista.

Aquí hay un fragmento de LINQPad :

var list = new List<int> { 1, 3, 2 };
var index = list.FindIndex(i => i == 2); // like Where/Single
if (index >= 0) {   // ensure item found
    list.RemoveAt(index);
}
list.Dump();        // results -> 1, 3

Feliz codificación


fuente
4

No especifica qué tipo de lista, pero la Lista genérica puede usar el RemoveAt(index)método o el Remove(obj)método:

// Remove(obj)
var item = resultList.Single(x => x.Id == 2);
resultList.Remove(item);

// RemoveAt(index)
resultList.RemoveAt(1);
mgnoonan
fuente
4

Más simplificado:

resultList.Remove(resultList.Single(x => x.Id == 2));

no es necesario crear un nuevo objeto var.

Javier Andres Caicedo
fuente
0

... o simplemente resultlist.RemoveAt(1)si sabes exactamente el índice.

Vlad
fuente
0
{
    class Program
    {
        public static List<Product> list;
        static void Main(string[] args)
        {

            list = new List<Product>() { new Product() { ProductId=1, Name="Nike 12N0",Brand="Nike",Price=12000,Quantity=50},
                 new Product() { ProductId =2, Name = "Puma 560K", Brand = "Puma", Price = 120000, Quantity = 55 },
                 new Product() { ProductId=3, Name="WoodLand V2",Brand="WoodLand",Price=21020,Quantity=25},
                 new Product() { ProductId=4, Name="Adidas S52",Brand="Adidas",Price=20000,Quantity=35},
                 new Product() { ProductId=5, Name="Rebook SPEED2O",Brand="Rebook",Price=1200,Quantity=15}};


            Console.WriteLine("Enter ProductID to remove");
            int uno = Convert.ToInt32(Console.ReadLine());
            var itemToRemove = list.Find(r => r.ProductId == uno);
            if (itemToRemove != null)
                list.Remove(itemToRemove);
            Console.WriteLine($"{itemToRemove.ProductId}{itemToRemove.Name}{itemToRemove.Brand}{itemToRemove.Price}{ itemToRemove.Quantity}");
            Console.WriteLine("------------sucessfully Removed---------------");

            var query2 = from x in list select x;
            foreach (var item in query2)
            {
                /*Console.WriteLine(item.ProductId+" "+item.Name+" "+item.Brand+" "+item.Price+" "+item.Quantity );*/
                Console.WriteLine($"{item.ProductId}{item.Name}{item.Brand}{item.Price}{ item.Quantity}");
            }

        }

    }
}
Prabhakaran M
fuente