score:1271

Accepted answer

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

score:0

to keep the code fluent (if code optimisation is not crucial) and you would need to do some further operations on the list:

authorslist = authorslist.where(x => x.firstname != "bob").<do_some_further_linq>;

or

authorslist = authorslist.where(x => !settoremove.contains(x)).<do_some_further_linq>;

score:1

i think you just have to assign the items from author list to a new list to take that effect.

//assume oldauthor is the old list
author newauthorlist = (select x from oldauthor where x.firstname!="bob" select x).tolist();
oldauthor = newauthorlist;
newauthorlist = null;

score:4

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.

note on immutability (taken from another so answer):

here is the definition of immutability from wikipedia.

in object-oriented and functional programming, an immutable object is an object whose state cannot be modified after it is created.

score:5

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.

score:5

below is the example to remove the element from the list.

 list<int> items = new list<int>() { 2, 2, 3, 4, 2, 7, 3,3,3};

 var result = items.remove(2);//remove the first ocurence of matched elements and returns boolean value
 var result1 = items.removeall(lst => lst == 3);// remove all the matched elements and returns count of removed element
 items.removeat(3);//removes the elements at the specified index

score:6

say that authorstoremove is an ienumerable<t> that contains the elements you want to remove from authorslist.

then here is another very simple way to accomplish the removal task asked by the op:

authorslist.removeall(authorstoremove.contains);

score:8

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.

score:9

this is a very old question, but i found a really simple way to do this:

authorslist = authorslist.except(authors).tolist();

note that since the return variable authorslist is a list<t>, the ienumerable<t> returned by except() must be converted to a list<t>.

score:21

i was wondering, if there is any difference between removeall and except and the pros of using hashset, so i have done quick performance check :)

using system;
using system.collections.generic;
using system.diagnostics;
using system.linq;
using system.text;

namespace listremovetest
{
    class program
    {
        private static random random = new random( (int)datetime.now.ticks );

        static void main( string[] args )
        {
            console.writeline( "be patient, generating data..." );

            list<string> list = new list<string>();
            list<string> toremove = new list<string>();
            for( int x=0; x < 1000000; x++ )
            {
                string randstring = randomstring( random.next( 100 ) );
                list.add( randstring );
                if( random.next( 1000 ) == 0 )
                    toremove.insert( 0, randstring );
            }

            list<string> l1 = new list<string>( list );
            list<string> l2 = new list<string>( list );
            list<string> l3 = new list<string>( list );
            list<string> l4 = new list<string>( list );

            console.writeline( "be patient, testing..." );

            stopwatch sw1 = stopwatch.startnew();
            l1.removeall( toremove.contains );
            sw1.stop();

            stopwatch sw2 = stopwatch.startnew();
            l2.removeall( new hashset<string>( toremove ).contains );
            sw2.stop();

            stopwatch sw3 = stopwatch.startnew();
            l3 = l3.except( toremove ).tolist();
            sw3.stop();

            stopwatch sw4 = stopwatch.startnew();
            l4 = l4.except( new hashset<string>( toremove ) ).tolist();
            sw3.stop();


            console.writeline( "l1.len = {0}, time taken: {1}ms", l1.count, sw1.elapsed.totalmilliseconds );
            console.writeline( "l2.len = {0}, time taken: {1}ms", l1.count, sw2.elapsed.totalmilliseconds );
            console.writeline( "l3.len = {0}, time taken: {1}ms", l1.count, sw3.elapsed.totalmilliseconds );
            console.writeline( "l4.len = {0}, time taken: {1}ms", l1.count, sw3.elapsed.totalmilliseconds );

            console.readkey();
        }


        private static string randomstring( int size )
        {
            stringbuilder builder = new stringbuilder();
            char ch;
            for( int i = 0; i < size; i++ )
            {
                ch = convert.tochar( convert.toint32( math.floor( 26 * random.nextdouble() + 65 ) ) );
                builder.append( ch );
            }

            return builder.tostring();
        }
    }
}

results below:

be patient, generating data...
be patient, testing...
l1.len = 985263, time taken: 13411.8648ms
l2.len = 985263, time taken: 76.4042ms
l3.len = 985263, time taken: 340.6933ms
l4.len = 985263, time taken: 340.6933ms

as we can see, best option in that case is to use removeall(hashset)

score:23

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)
    {
        //
    }
}

score:33

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

score:56

if you really need to remove items then what about except()?
you can remove based on a new list, or remove on-the-fly by nesting the linq.

var authorslist = new list<author>()
{
    new author{ firstname = "bob", lastname = "smith" },
    new author{ firstname = "fred", lastname = "jones" },
    new author{ firstname = "brian", lastname = "brains" },
    new author{ firstname = "billy", lastname = "thekid" }
};

var authors = authorslist.where(a => a.firstname == "bob");
authorslist = authorslist.except(authors).tolist();
authorslist = authorslist.except(authorslist.where(a=>a.firstname=="billy")).tolist();

score:154

it'd be better to use list<t>.removeall to accomplish this.

authorslist.removeall((x) => x.firstname == "bob");

Related Query

More Query from same tag