I have 2 lists: list1
and list2
(both of type int)
Now I want to remove content of list2
from list1
. How I can do this in C#?
PS: Don't use loop.
IMPORTANT CHANGE
As was pointed out in the comments, .Except()
uses a set internally, so any duplicate members of list1
will be absent in the final result.
Produces the set difference of two sequences
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.except(v=vs.110).aspx
However, there is a solution that is both O(N) and preserves duplicates in the original list: Modify the RemoveAll(i => list2.Contains(i))
approach to use a HashSet<int>
to hold the exclusion set.
List<int> list1 = Enumerable.Range(1, 10000000).ToList();
HashSet<int> exclusionSet = Enumerable.Range(500000, 10).ToHashSet();
list1.Remove(i => exclusionSet.Contains(i));
The extension method ToHashSet()
is available in MoreLinq.
ORIGINAL ANSWER
You can use Linq
list1 = list1.Except(list2).ToList();
UPDATE
Out of curiosity I did a simple benchmark of my solution vs. @HighCore's.
For list2
having just one element, his code is faster. As list2
gets larger and larger, his code gets extremely slow. It looks like his is O(N-squared) (or more specifically O(list1.length*list2.length) since each item in list1
is compared to each item in list2
). Don't have enough data points to check the Big-O of my solution, but it is much faster when list2
has more than a handful of elements.
Code used to test:
List<int> list1 = Enumerable.Range(1, 10000000).ToList();
List<int> list2 = Enumerable.Range(500000, 10).ToList(); // Gets MUCH slower as 10 increases to 100 or 1000
Stopwatch sw = Stopwatch.StartNew();
//list1 = list1.Except(list2).ToList();
list1.RemoveAll(i => list2.Contains(i));
sw.Stop();
var ms1 = sw.ElapsedMilliseconds;
UPDATE 2
This solution assigns a new list to the variable list1
. As @Толя points out, other references (if any) to the original list1
will not be updated. This solution drastically outperforms RemoveAll
for all but the smallest sizes of list2
. If no other references must see the update, it is preferable for that reason.
list1.RemoveAll(x => list2.Contains(x));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With