# How to create patterns for DeleteCases / Cases / Select: deleting elements of a list, from the condition of a negative element in a column

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.

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

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.

• Or Select[list, #[[2]] >= 0 &] or Cases[list, {_, _?NonNegative}] May 31, 2022 at 13:53
• @Bob Good point, he had indeed asked for those other approaches as well. I'll add those May 31, 2022 at 13:54

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.