Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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!

share|improve this question
add comment

5 Answers

up vote 20 down vote accepted

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.

share|improve this answer
    
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
show 2 more comments

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.

share|improve this answer
    
Uh, Leonid beat me here. Should I leave the answer here anyway? –  Yves Klett Feb 4 '12 at 9:05
3  
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
1  
@PeriodicProgrammer Next time, please remember to include what you've tried and your constraints (unsorted), so that people don't waste time suggesting that. –  rm -rf Feb 4 '12 at 13:25
add comment

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

share|improve this answer
add comment

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

DeleteDuplicates[#2 ~Join~ #] ~Drop~ Length[#2] &[list1, list2]
share|improve this answer
3  
Clever trick. +1. –  Leonid Shifrin Feb 4 '12 at 9:30
add comment

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.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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