9
$\begingroup$

I want to delete the complete list within a list containing 0 at any position.

I tried using:

DeleteCases[Tuples[Range[-2, 2], 2], {0 ..}]

{{-2, -2}, {-2, -1}, {-2, 0}, {-2, 1}, {-2, 2}, {-1, -2}, {-1, -1}, {-1, 0}, {-1, 1}, {-1, 2}, {0, -2}, {0, -1}, {0, 1}, {0, 2}, {1, -2}, {1, -1}, {1, 0}, {1, 1}, {1, 2}, {2, -2}, {2, -1}, {2, 0}, {2, 1}, {2, 2}}

But only the lists starting with 0 are removed.

How can I remove the entire list that contains 0 at any place?

$\endgroup$

3 Answers 3

8
$\begingroup$
 DeleteCases[Tuples[Range[-2, 2], 2], {___, 0, ___}] (* or *)
 DeleteCases[data, {0, 0}|{1,0}|{0,1}]

{{-2, -2}, {-2, -1}, {-2, 1}, {-2, 2}, {-1, -2}, {-1, -1}, {-1, 1}, {-1, 2}, {1, -2}, {1, -1}, {1, 1}, {1, 2}, {2, -2}, {2, -1}, {2, 1}, {2, 2}}

Alternatively, if you can, remove zeros from the input lists before using Tuples:

Tuples[Join[-Reverse@#, #]&@Range[2],2]

same result

Even if data = Tuples[Range[-2, 2], 2] is already created, processing data to create a zero-free input list and using Tuples on it is (to my surprise) faster than using Pick to remove entries with zeros from pairs of data:

data = Tuples[Range[-100, 100], 2];

ra = Tuples[Join[-Reverse @ #, #]& @ Range[100],2]; // RepeatedTiming // First

0.0000524

rb = With[{r = DeleteCases[DeleteDuplicates @ Flatten[data], 0]},
  Tuples[r, 2]];// RepeatedTiming // First  

0.000178

rc = Pick[data, Unitize[data].{1, 1}, 2];//RepeatedTiming//First (*from @Henrik's answer*)

0.0013

rd = DeleteCases[data, {0, 0}|{1,0}|{0,1}];// RepeatedTiming // First  

0.017

re = DeleteCases[data, {___, 0, ___}];// RepeatedTiming // First   

0.026

rf = Select[data, FreeQ[0] ];// RepeatedTiming // First  (*from David's answer *)

0.060

ra == rb == rc == rd == re == rf

True

$\endgroup$
5
  • $\begingroup$ Well.... if you're free to delete 0 before using Tuples simply use Tuples[{-2, -1, 1, 2}, 2]. $\endgroup$ Sep 12, 2018 at 20:15
  • $\begingroup$ @David, yes; i used the more cumbersome way to deal with cases like Range[-100, 100] $\endgroup$
    – kglr
    Sep 12, 2018 at 20:27
  • 1
    $\begingroup$ Oh, method b and c... nice out-of-the-box-thinking! $\endgroup$ Sep 12, 2018 at 21:42
  • $\begingroup$ DeleteCases[DeleteDuplicates @ Flatten[data], 0] is not packed, while Join[-Reverse @ #, #]& @ Range[100] is, explaining the difference in timing $\endgroup$
    – Carl Woll
    Sep 12, 2018 at 23:39
  • $\begingroup$ @CarlWoll, good point. But in this case, DeleteDuplicates @ Flatten[data] (which is packed) already takes 0.00011 seconds (RepeatedTiming) compared to 3.06*10^-6 for Join[-Reverse @ #, #]& @ Range[100], simply because the former processes a list with dimensions {40401,2} and the latter with just {200}. $\endgroup$
    – kglr
    Sep 13, 2018 at 0:28
7
$\begingroup$

Here a more cumbersome (not a code golfer) but faster approach:

data = Tuples[Range[-100, 100], 2];
a = DeleteCases[data, {___, 0, ___}]; // RepeatedTiming // First
b = Pick[data, Unitize[data].{1, 1}, 2]; // RepeatedTiming // First
a == b

0.028

0.00098

True

This skips pattern matching in favor of faster vectorized functions.

$\endgroup$
7
$\begingroup$

Or...

Select[Tuples[Range[-2, 2], 2], ! MemberQ[#, 0] &]

or as @ThatGravityGuy points out...

Select[Tuples[Range[-2, 2], 2], FreeQ[#, 0] &]
$\endgroup$
4
  • 1
    $\begingroup$ Instead of !MemberQ couldn't you just use FreeQ? $\endgroup$ Sep 12, 2018 at 19:45
  • $\begingroup$ Oooh... of course. Yes. Thanks. $\endgroup$ Sep 12, 2018 at 19:47
  • $\begingroup$ You can use the operator form FreeQ[0] instead of FreeQ[#, 0] & $\endgroup$
    – kglr
    Sep 12, 2018 at 21:36
  • 1
    $\begingroup$ .. or operator forms of both Select and FreeQ: Select[FreeQ@0]@data $\endgroup$
    – kglr
    Sep 12, 2018 at 23:17

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.