4
$\begingroup$

I've been trying to create a simple and "human readable" instruction for deleting elements from a list with an specific pattern.

I have the following list and I would like to delete the elements containing a negative number on the second column.

In[1]:= list = {{1,2},{3,-4},{-5,6},{7,8}};

I've found a nice solution in this question. However, this eliminates any element with a negative number.: Deleting Negative Point from an array of arrays

In[2]:= DeleteCases[_?(AnyTrue[Negative]@#&)] @ list
Out[2]= {{1,2},{7,8}}

My desired output would be:

Out[X]=  {{1,2},{-5,6},{7,8}};

Could maybe someone recommend a source where to learn advanced pattern construction?

I've seen was involving underscores _, like: {_,_Negative}, but I'm not really clear on how to use it within DeleteCases functions. I found a nice presentation with slight details, but maybe a wider explanation would be handy.

$\endgroup$
5
  • 3
    $\begingroup$ DeleteCases[list, {_, _?Negative}] $\endgroup$
    – MarcoB
    May 31, 2022 at 13:18
  • $\begingroup$ Works amazingly! Could you write it as an answer? @MarcoB $\endgroup$ May 31, 2022 at 13:21
  • $\begingroup$ Done! I've added a little bit of context. Hopefully it will be helpful $\endgroup$
    – MarcoB
    May 31, 2022 at 13:38
  • $\begingroup$ list /. {_, x_} /; x < 0 -> Nothing $\endgroup$
    – Syed
    May 31, 2022 at 14:49
  • 2
    $\begingroup$ Pick[#,UnitStep[#[[All,2]]],1]&@list or (more 'human readable'?) Pick[list,NonNegative@list[[All,2]]] $\endgroup$
    – user1066
    May 31, 2022 at 15:37

2 Answers 2

8
$\begingroup$

You were right that such a pattern would involve _ (i.e. Blank) and a PatternTest (? for short):

DeleteCases[list, {_, _?Negative}]
Cases[list, {_, _?NonNegative}] 

Above we are looking for a list of two elements, the second of which should return True when Negative or NonNegative is applied to it.


Select is slightly different because it is not pattern-based, but instead it uses a selector function:

Select[list, #[[2]] >= 0 &]

As a note for future reference, when you find yourself using your own function instead of a built-in like Negative in the pattern test, wrap it in parentheses to avoid precedence issues. In this case, for instance, you could have written # < 0 & instead of Negative:

DeleteCases[list, {_, _?(# < 0 &)}]

If you try it without the parentheses, you will not get what you expect because PatternTest has higher precedence than Function.

$\endgroup$
3
  • 4
    $\begingroup$ Or Select[list, #[[2]] >= 0 &] or Cases[list, {_, _?NonNegative}] $\endgroup$
    – Bob Hanlon
    May 31, 2022 at 13:53
  • 1
    $\begingroup$ @Bob Good point, he had indeed asked for those other approaches as well. I'll add those $\endgroup$
    – MarcoB
    May 31, 2022 at 13:54
  • $\begingroup$ @Nikodem Are you sure you are using list as defined in the OP? Your code does nothing on that list. $\endgroup$
    – MarcoB
    Mar 19 at 16:24
5
$\begingroup$

In such a simple case, @MarcoB's and @BobHanlon's answers are the way to go. In other words, use a pure function that tests a part of the desired element of each sublist, as in

Select[list,#[[2]]>0&]
(*{{1, 2}, {-5, 6}, {7, 8}}*)

However, it is interesting that some functions use different constructs. For example Count operates differently. For me, to preserve readability in those, I need to give a name to the sublists and create a conditional expression:

Count[list,sublist_/;sublist[[2]]>0]
(*3*)

This counts all the sublists, conditional on (/;) their second element being positive. The alternative, which is not readable if the sublists become complex, is to use patterns all the way, as in

Count[list, {_, _?NonNegative,___}]

This counts sublists with two or more elements, the second one of which is positive. Bob can probably explain this difference between Select and Count in a way that makes sense.

$\endgroup$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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