3
$\begingroup$

I need to use Position to obtain positions of entries in list of lists that do not contain a certain pattern.

The problem is that Position wants the pattern to find. Not the pattern to avoid.

Also Position does not take in a pure function, which one can use to do the checking and return True or False.

I do not know how to tell Position to look for entries that do not match a given pattern. Here is an example

lis = {{Tan[x], Exp[x]}, {3, x + Sin[x], 7}, {5, Cos[x], 99}}

I want to find positions of entries that does not contain the pattern Sin[_]

It is easy to find the position which contains the pattern

Position[lis, Sin[_]]
(* {{2, 2, 2}} *)

But how to do the opposite? FreeQ does not work. The thing that goes at the end has to be a pattern.

I am not looking for other functions such as Select and Cases. I need to use Position in order to obtain the actual positions to use with Extract for example.

I looked at FunctionRepository/resources/SelectPositions and even though this does allow one to use a function, it does not return Positions in same format Position command does.

Here is an example. Lets find entries with Sin[_] in it

lis = {{Tan[x], Exp[x]}, {3, x + Sin[x], 7}, {5, Cos[x], 99}}
foo = Not[FreeQ[#, Sin[_]]] &;
p = ResourceFunction["SelectPositions"][lis, foo]
(* {{2}} *)

Compare to

lis = {{Tan[x], Exp[x]}, {3, x + Sin[x], 7}, {5, Cos[x], 99}}
Position[lis, Sin[_]]

(* {{2, 2, 2}} *)

The question again is: I would like to use Position to specify not the pattern to find, but the pattern to avoid.

So it will return all those positions which do not have this pattern. For the above example those positions will be by inspection (assuming I did it right)

 {{1,1},{1,2},  {2,1},{2,2,1},{2,3},  {3,1},{3,2},{3,3} }

Any suggestions?

V 13.2

$\endgroup$
6
  • 3
    $\begingroup$ pos = Position[lis, Except[Sin[_]], {2}, Heads -> False] ? $\endgroup$
    – Syed
    Feb 25 at 17:56
  • $\begingroup$ @Syed I did not know I could use Except[pattern]. This looks promissing. I do not know why it returns {{1, 1}, {1, 2}, {2, 1}, {2, 2}, {2, 3}, {3, 1}, {3, 2}, {3, 3}} instead of what I was expecting {{1,1},{1,2}, {2,1},{2,2,1},{2,3}, {3,1},{3,2},{3,3} } but this is not important now, will look at it more. But I think this should work if you like to make it an answer. I think help for Position should had an example using Except ! $\endgroup$
    – Nasser
    Feb 25 at 18:00
  • 3
    $\begingroup$ Position[lis, _?(Head[#] =!= Sin &)] or Position[lis, _?(FreeQ[#, Sin] &)] $\endgroup$
    – Bob Hanlon
    Feb 25 at 18:10
  • $\begingroup$ @BobHanlon thanks. But I need to specify a pattern. This was just an example, and to make it general, I'd like to use a pattern to avoid. Your's work if I am looking for entries that do not have Sin, but again, this was just an example. Except allows one to use a pattern inside, and I just did not know about it. $\endgroup$
    – Nasser
    Feb 25 at 18:14
  • 3
    $\begingroup$ You can put any pattern that you want into the PatternTest including (as shown) those that contain pure functions. $\endgroup$
    – Bob Hanlon
    Feb 25 at 18:19

2 Answers 2

7
$\begingroup$

As far as I understand it, Except is a pattern object and it fits with pattern matching.

lis = {{Tan[x], Exp[x]}, {3, x + Sin[x], 7}, {5, Cos[x], 99}}


pos = Position[lis, Except[Sin[_]], {2}, Heads -> False]

FreeQ is a function on the other hand and you can use the PatternTest construct to use it to search for the lack of a pattern.

pos2 = Position[lis, _?(FreeQ[Sin[_]]), {2}, Heads -> False]

Moreover, Position will search through Head by default so you have to restrict that and search at the level required. You can experiment with these options further.


Result:

{{1, 1}, {1, 2}, {2, 1}, {2, 3}, {3, 1}, {3, 2}, {3, 3}}


Regarding the pure function, the PatternTest construct works; e.g.,

pos3 = Position[lis, _?(# > 2 &), {2}, Heads -> False]

{{2, 1}, {2, 3}, {3, 1}, {3, 3}}

Extract[lis, pos3]

{3, 7, 5, 99}

$\endgroup$
1
$\begingroup$
ps = Position[lis,x_/;Head[x]=!=Sin,{2},Heads->False]

(* {{1,1},{1,2},{2,1},{2,2},{2,3},{3,1},{3,2},{3,3}} *)
$\endgroup$

Your Answer

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

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