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:


I can now remove list2 from list1:


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!

  • 1
    $\begingroup$ Not functional, but just for fun: list1 /. Thread[list2 -> Nothing] $\endgroup$ – user1066 Apr 7 '16 at 20:08


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.

  • $\begingroup$ thank you a lot, I do have V.8 and it works perfectly! Thank you for the fast answer! $\endgroup$ – PeriodicProgrammer Feb 4 '12 at 9:07
  • $\begingroup$ Thanks for including version-specific information; if you had not I would be left guessing. $\endgroup$ – Mr.Wizard Feb 4 '12 at 9:38
  • $\begingroup$ Thanks a lot, this works for any nested list! :) Great solution! $\endgroup$ – Lady InRed Oct 5 '12 at 9:58
  • $\begingroup$ @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 $\endgroup$ – Leonid Shifrin Oct 5 '12 at 14:24
  • $\begingroup$ @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? $\endgroup$ – 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.

  • 1
    $\begingroup$ Uh, Leonid beat me here. Should I leave the answer here anyway? $\endgroup$ – Yves Klett Feb 4 '12 at 9:05
  • 3
    $\begingroup$ 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). $\endgroup$ – Leonid Shifrin Feb 4 '12 at 9:10
  • $\begingroup$ yes this is true. I found Complement on google, but I need the result to be unsorted. $\endgroup$ – PeriodicProgrammer Feb 4 '12 at 9:50
  • 3
    $\begingroup$ @PeriodicProgrammer Next time, please remember to include what you've tried and your constraints (unsorted), so that people don't waste time suggesting that. $\endgroup$ – rm -rf 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]
  • 3
    $\begingroup$ Clever trick. +1. $\endgroup$ – Leonid Shifrin Feb 4 '12 at 9:30
  • $\begingroup$ This will keep list 1 in its original order—just what I was looking for! $\endgroup$ – Szabolcs Oct 10 '20 at 15:40

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[]] := 
   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.


Just nest it:

Fold[DeleteCases[#1, #2] &, list1, list2]

I hesitate to add to this old discussion after these excellent answers and other essential reading especially here, but this amalgamation of many suggestions may be of interest. cutEverything[xx_, removeList__] removes all entries of all elements of removeList_ from xx_ regardless of their depth or whether they are duplicates. It leaves compounds in place and does not change the original list order.

x = 
  {pudepied, pudepied.txt, {pudepied}, {{{pudepied}}, {zap}, {{peter}}}, {{pudepied}}, 
   blah, zap, "Wolfram Language", {peter}, {{{}}}, mary, {{{{mary}}}}};

remove = {pudepied, peter, mary, {}};
cutEverything[xx_, removeList_] := 
  Replace[xx, x_List :> DeleteCases[x, Alternatives @@ removeList], {0, Infinity}]
cutEverything[x, remove]
 {pudepied.txt, {{zap}}, blah, zap, Wolfram Language}
  • $\begingroup$ Very nice, but I think you need to remove a right paren from the {{pudepied}}}, that follows the first occurrence of peter, else an error appears. $\endgroup$ – Christopher Lamb Sep 28 '20 at 2:30
  • $\begingroup$ Thank you. Fixed! $\endgroup$ – pudepied Sep 28 '20 at 10:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.