5
$\begingroup$

If I have a list of numbers {1, 2, 4, 70, 11, 20, 56, 79}, is there a way to remove the list {2, 4, 56} from that list?

In my application, the lists are way bigger, so I am looking for a general way of removing a list of numbers from the original list.

My thoughts were to use the following code: DeleteCases[{1, 2, 4, 70, 11, 20, 56, 79}, {2, 4, 56}] but that didn't work, because the output must be {1, 70, 11, 20, 79} and it isn't.

$\endgroup$
4
  • 1
    $\begingroup$ You coud try: DeleteCases[{1, 2, 4, 70, 11, 20, 56, 79}, x_ /; MemberQ[{2, 4, 56}, x]] $\endgroup$ Commented Jan 13, 2021 at 17:20
  • 8
    $\begingroup$ Just a little correction of your code DeleteCases[{1, 2, 4, 70, 11, 20, 56, 79}, Alternatives@@{2,4,56}] should do the trick. $\endgroup$ Commented Jan 13, 2021 at 17:44
  • 1
    $\begingroup$ Strongly related: How to Delete Elements from List1 appearing in List2? $\endgroup$ Commented Jan 13, 2021 at 18:00
  • 1
    $\begingroup$ Also, unsorted complement $\endgroup$ Commented Jan 13, 2021 at 18:02

4 Answers 4

8
$\begingroup$

There are three main ways of deleting members in such cases :

  1. As Daniel said , you could try DeleteCases supplementing a pattern which picks up just the numbers which are element of another list. The pattern is like this :

as what Daniel said :

a_ /; MemberQ[{2,4,56},a] 

or :

a_?(MemberQ[{2, 4, 56}, #] &) 

Now you could use each one of the above patterns in DeleteCases. Thus we have :

DeleteCases[{1, 2, 4, 70, 11, 20, 56, 79} , a_ /; MemberQ[{2,4,56},a])] 

or :

DeleteCases[{1, 2, 4, 70, 11, 20, 56, 79} , a_?(MemberQ[{2, 4, 56}, #] &)] 
  1. But there is even a simpler way of deleting cases which could be tried.

This is a sample :

{1, 2, 4, 70, 11, 20, 56, 79} /. a_ /; MemberQ[{2, 4, 56}, a] -> Nothing 

In this way we could just convert any instance matching your pattern to Nothing ! ( Converting THING to NOTHING. isn't better?! )

  1. And even simpler :

Just using Complement :

Complement[{1, 2, 4, 70, 11, 20, 56, 79}, {2, 4, 56}] 

BE CAUTIONED !! Using each one of the mentioned ways WILL NOT take the same (asymptotically) time to evaluate.

Just for representation , we could compare these two ways in list with length of 10^6 :

For the first route :

AbsoluteTiming[ Table[DeleteCases[Range[10^6], a_?(MemberQ[RandomInteger[10^6, 100], #] &)];, 5]] // First 

which gives me 124.474 (means 124 seconds).

And for the second way:

AbsoluteTiming[ Table[Range[10^6] /. a_ /; MemberQ[RandomInteger[10^6, 100], a] -> Nothing;, 5]] // First 

Which gives me 124.8 (means 124 seconds).

While the third way :

AbsoluteTiming[ Table[Complement[Range[10^6], RandomInteger[10^6, 100]];, 5]] // First 

just take 0.15 (means 0.15 seconds) !!

Compare those : 124 sec, 124 sec , 0.15 sec

So the best way is the third way especially for larger Lists ! :)

$\endgroup$
1
  • 3
    $\begingroup$ Complement is not guaranteed to retain the order, e.g., Complement[{4, 3, 2, 1}, {1, 3}] returns {2,4} $\endgroup$ Commented Jan 13, 2021 at 19:03
2
$\begingroup$
list = {1, 2, 4, 70, 11, 20, 56, 79}; d = {2, 4, 56}; 

Using DeleteElements (new in 13.1)

DeleteElements[list, d] 

{1, 70, 11, 20, 79}

Complement, suggested in the accepted answer, sorts the result:

Complement[list, d] 

{1, 11, 20, 70, 79}

$\endgroup$
2
$\begingroup$
list = {1, 2, 4, 70, 11, 20, 56, 79}; d = {2, 4, 56}; 

Using Position and Delete:

Delete[#, Position[#, Alternatives @@ d]] &@list (*{1, 70, 11, 20, 79}*) 

Or using Pick:

Pick[#, And @@ Thread[# != d] & /@ #] &@list (*{1, 70, 11, 20, 79}*) 
$\endgroup$
1
$\begingroup$
vis = {2, 4, 56} // AssociationMap[True&]; {1, 2, 4, 70, 11, 20, 56, 79} // Select[!KeyExistsQ[#][vis]&] 

$O(n)$ and keep the order.

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.