4
$\begingroup$

trying to do a pattern matching on a list, I want to find the two members that are negatives of each other, i.e.:

{0.,1.5,-1.5,4.2}

I tried:

listOfNumbers/. {x___, PatternSequence[z__, -z__], y___} :> {z}

And every similar case, but I am missing something. Any ideas?

$\endgroup$
2
  • $\begingroup$ Might there be several pairs of a, -a? $\endgroup$ – David G. Stork Apr 5 '17 at 18:00
  • $\begingroup$ No, there is only one. $\endgroup$ – Morgan Apr 5 '17 at 18:09
5
$\begingroup$
Position[MovingAverage[mylist, 2], 0.]

Example:

mylist = {4, 6.8, 7.3, -7.3, 14, 22, π};

Position[MovingAverage[mylist, 2], 0.]

{{3}}

You can then select from mylist element 3 (and subsequent one).

Or:

mylist[[Position[MovingAverage[mylist, 2], 0][[1]]]]

{7}

It even works with functions that must be evaluated:

mylist = {4, 6.8, -2, 
   Limit[4 x^2/(2 x^2 + 1), x -> \[Infinity]], -7.3, 14, 22, π};
$\endgroup$
3
  • $\begingroup$ Great, thank you. Is there a simple way to extend this to the case when the two elements are last and first? I know I can append the first element to thee end of the list before doing this, but if there is a simpler way, let me know, please. $\endgroup$ – Morgan Apr 5 '17 at 18:12
  • $\begingroup$ I would simply append the first element onto the end of the list. So... is my answer acceptable (with a green check or up-vote)? $\endgroup$ – David G. Stork Apr 5 '17 at 18:13
  • $\begingroup$ Yep, just accepted it. The only change I needed to do was 0. instead of 0 as my list contains floats. $\endgroup$ – Morgan Apr 5 '17 at 18:15
5
$\begingroup$

There are much more efficient ways to do this simple task vs pattern matching, e.g.:

adjacentOpSign=Pick[Range@Length@#, Unitize[# + RotateLeft@#], 0] &;

adjacentOpSign@{4, 6.8, 7.3, -7.3, 14, 22, π}

{3}

This will be orders of magnitude faster for large lists, and automatically accounts for your cyclic (first and last meet criteria) needs...

$\endgroup$
4
$\begingroup$

using patterns:

{0., 1.5, -1.5, 4.2} /. {___, PatternSequence[a_, b_] /; b == -a, ___} :> a

1.5

or to deal with floating point issues you might want this:

{0., 1.5, -1.5, 4.2} /. {___, PatternSequence[a_, b_] /; Chop[a+b]==0, ___} :> a
$\endgroup$

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.