# How to Delete Elements from List1 appearing in List2?

I'm new to functional programming of Mathematica and trying to remove one list of assorted elements from another. However I only find functions working with the Index rather than the values itself:

 list1={b,a,e,f,c,d}
list2={f,e,c}


I can now remove list2 from list1:

 result={b,a,d}


I already found out, that you can "abuse"

DeleteCases[list1, a]


to remove 1 specific element from a list, but not a whole assorted list...

I would be very grateful for a simple solution to do it.
Thanks a lot for any answer!

-

Use

DeleteCases[list1, Alternatives @@ list2]


In new versions (M8.0+), DeleteCases is optimized on patterns not involving blanks, so this will be fast also for large lists. For earlier versions, this will work:

Replace[list1, Dispatch[Thread[list2 -> Sequence[]]],{1}]


being 2-3 times slower, but still very fast.

-
thank you a lot, I do have V.8 and it works perfectly! Thank you for the fast answer! – PeriodicProgrammer Feb 4 '12 at 9:07
Thanks for including version-specific information; if you had not I would be left guessing. – Mr.Wizard Feb 4 '12 at 9:38
Thanks a lot, this works for any nested list! :) Great solution! – Lady InRed Oct 5 '12 at 9:58
@AnastasiiaAnishchenko No problem :-). Actually, it only works on level 1. You probably meant that elements can be anything, including being themselves lists. Actually, I have developed a more general set of routines for similar kinds of operations, see the UnsortedOperations package on this page – Leonid Shifrin Oct 5 '12 at 14:24
@LeonidShifrin I am curious about the principle of DeleteCases. Why is it so fast than Select[list1, FreeQ[list2, #] &]? And I don't know the principle of Dispatch either. May be they have the same principle? – matheorem Nov 21 '13 at 13:37

You are perhaps searching for Complement. Complement[list1, list2] results in {a, b, d}. The result is sorted though. If you are looking for an unsorted complement, DeleteCases[list1, Alternatives @@ list2] should probably work. I think there are some discussions on unsorted complements out there at google.

-
Uh, Leonid beat me here. Should I leave the answer here anyway? – Yves Klett Feb 4 '12 at 9:05
Keep it, why not? I did not mention Complement (I actually implicitly assumed that the resulting list should not be sorted, which may or may not be the case). – Leonid Shifrin Feb 4 '12 at 9:10
yes this is true. I found Complement on google, but I need the result to be unsorted. – PeriodicProgrammer Feb 4 '12 at 9:50
@PeriodicProgrammer Next time, please remember to include what you've tried and your constraints (unsorted), so that people don't waste time suggesting that. – R. M. Feb 4 '12 at 13:25

Iff each list is internally free of duplicates you can use this very quick method:

DeleteDuplicates[#2 ~Join~ #] ~Drop~ Length[#2] &[list1, list2]

-
Clever trick. +1. – Leonid Shifrin Feb 4 '12 at 9:30

Since Yves beat me narrowly to my first solution, here's another one using Select:

Select[list1, FreeQ[list2, #] &]
Out[2]= {b, a, d}


This does not sort your result.

You can also use Complement, which is more intuitive. Example:

Complement[list1, list2]
Out[1]= {a, b, d}


Note that this sorts your result (i.e., it is not in the same order, {b, a, d}).

-

Unsorted Complement. I think it originates from MathGroup. It accepts the SameTest option.

Options[UnsortedComplement] = {SameTest -> Automatic};
UnsortedComplement[all_, del___, opts : OptionsPattern[]] :=
Replace[all,
List @@ (Rule[#, Sequence[]] & /@ Union[del, opts]), {1}];

all = RandomInteger[{0, 9}, {20}]
UnsortedComplement[all, {6, 2, 8}, {2, 3, 4}]

(*
==> {8, 4, 2, 5, 8, 8, 6, 6, 2, 1, 3, 1, 1, 2, 8, 0, 5, 5, 8, 1}

==> {5, 1, 1, 1, 0, 5, 5, 1}
*)


It also works with any head, not just List-s.

-