[c#] How to remove item from list in C#?

I have a list stored in resultlist as follows:

var resultlist = results.ToList();

It looks something like this:

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

How do I remove ID 2 from the list?

This question is related to c# list

The answer is


More simplified:

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

there is no needing to create a new var object.


You don't specify what kind of list, but the generic List can use either the RemoveAt(index) method, or the Remove(obj) method:

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

// RemoveAt(index)
resultList.RemoveAt(1);

There is another approach. It uses List.FindIndex and List.RemoveAt.

While I would probably use the solution presented by KeithS (just the simple Where/ToList) this approach differs in that it mutates the original list object. This can be a good (or a bad) "feature" depending upon expectations.

In any case, the FindIndex (coupled with a guard) ensures the RemoveAt will be correct if there are gaps in the IDs or the ordering is wrong, etc, and using RemoveAt (vs Remove) avoids a second O(n) search through the list.

Here is a LINQPad snippet:

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

Happy coding.


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

There's a little Linq helper I like that's easy to implement and can make queries with "where not" conditions a little easier to read:

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();

{
    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}");
            }

        }

    }
}

Short answer:
Remove (from list results)

results.RemoveAll(r => r.ID == 2); will remove the item with ID 2 in results (in place).

Filter (without removing from original list results):

var filtered = result.Where(f => f.ID != 2); returns all items except the one with ID 2

Detailed answer:

I think .RemoveAll() is very flexible, because you can have a list of item IDs which you want to remove - please regard the following example.

If you have:

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

and assigned some values to results as follows:

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

Then you can define a list of IDs to remove:

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

And simply use this to remove them:

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

It will remove the items 2 and 3 and keep the items 1 and 4 - as specified by the removeList. Note that this happens in place, so there is no additional assigment required.

Of course, you can also use it on single items like:

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

where it will remove Bill with ID 4 in our example.

A last thing to mention is that lists have an indexer, that is, they can also be accessed like a dynamic array, i.e. results[3] will give you the 4th element in the results list (because the first element has the index 0, the 2nd has index 1 etc).

So if you want to remove all entries where the first name is the same as in the 4th element of the results list, you can simply do it this way:

results.RemoveAll(r => results[3].FirstName == r.FirstName);

Note that afterwards, only John and Doug will remain in the list, Bill is removed (the first and last element in the example). Important is that the list will shrink automatically, so it has only 2 elements left - and hence the largest allowed index after executing RemoveAll in this example is 1
(which is results.Count() - 1).

Some Trivia: You can use this knowledge and create a local function

void myRemove()  { var last = results.Count() - 1; 
                   results.RemoveAll(r => results[last].FirstName == r.FirstName); }

What do you think will happen, if you call this function twice? Like

myRemove(); myRemove(); 

The first call will remove Bill at the first and last position, the second call will remove Doug and only John Wilson remains in the list.


DotNetFiddle: Run the demo

Note: Since C# Version 8, you can as well write results[^1] instead of var last = results.Count() - 1; and results[last]:

void myRemove() { results.RemoveAll(r => results[^1].FirstName == r.FirstName); }

So you would not need the local variable last anymore (see indices and ranges. For a list of all the new features in C#, look here).


... or just resultlist.RemoveAt(1) if you know exactly the index.