tags:

views:

7899

answers:

7

I have LINQ query such as:

var authors = from x in authorsList
              where x.firstname == "Bob"
              select x;

Given that authorsList is of type List, how can I delete any Author that appears within 'var authors' from authorsList?

Note: This is a simplified example for the purposes of the question.

+42  A: 

Well, it would be easier to exclude them in the first place:

authorsList = authorsList.Where(x => x.FirstName != "Bob").ToList();

However, that would just change the value of authorsList instead of removing the authors from the previous collection. Alternatively, you can use RemoveAll:

authorsList.RemoveAll(x => x.FirstName == "Bob");

If you really need to do it based on another collection, I'd use a HashSet, RemoveAll and Contains:

var setToRemove = new HashSet<Author>(authors);
authorsList.RemoveAll(x => setToRemove.Contains(x));
Jon Skeet
+2  A: 

You cannot do this with standard LINQ operators because LINQ provides query, not update support.

But you can generate a new list and replace the old one.

var authorsList = GetAuthorList();

authorsList = authorsList.Where(a => a.FirstName != "Bob").ToList();

Or you could remove all items in authors in a second pass.

var authorsList = GetAuthorList();

var authors = authorsList.Where(a => a.FirstName == "Bob").ToList();

foreach (var author in authors)
{
    authorList.Remove(author);
}
Daniel Brückner
+9  A: 

It'd be better to use List<T>.RemoveAll to accomplish this.

authorsList.RemoveAll((x) => x.firstname == "Bob");
Reed Copsey
@Reed Copsey: The lambda parameter in your example is enclosed in parentheses, i.e., (x). Is there a technical reason for this? Is it considered good practice?
Matt Davis
No. It's required with >1 parameter. With a single parameter, it's optional, but it does help keep consistency.
Reed Copsey
+2  A: 

LINQ has its origins in functional programming, which emphasises immutability of objects, so it doesn't provide a built-in way to update the original list in-place.

Samuel Jack
+2  A: 

Simple solution:

static void Main()
        {
            List<string> myList = new List<string> {"Jason", "Bob", "Frank", "Bob"};

            myList.RemoveAll(x => x == "Bob");

            foreach (string s in myList)
            {
                Console.WriteLine(s);
            }

            Console.ReadLine();
        }
Jason Heine
+1  A: 

I think you could do something like this

    authorsList = (from a in authorsList
                  where !authors.Contains(a)
                  select a).ToList();

Although I think the solutions already given solve the problem in a more readable way.

ebrown
+3  A: 

You can remove in two ways

var output=from x in authorsList
              where x.firstname != "Bob"
              select x;

OR

var authors = from x in authorsList
              where x.firstname == "Bob"
              select x; var output=from x in authorsList
              where !authors.Contains(x) 
              select x;

I had same issue, if you want simple output based on your where condition , then first solution is better.

Thanks

Asif

AsifQadri