2
$\begingroup$

My overall goal was to produce a list of heads used in a graphics output.

For an example I used:

rp3D = FullForm[RevolutionPlot3D[{2 + Cos[t], Sin[t]}, {t, 0, 2 Pi}]];

and then

graphicsList = 
 Union[Flatten[rp3D //. f_[x__] /; UnsameQ[f, List] -> {f, x}]]

Union places all of the numerical values first. All I have to do is remove those elements and my goal is achieved.

I attempted to remove the numerical values using patterns and rules and found myself in my usual state of confusion and failure.

To resolve this I simplified the problem.

fakeList = {1, 2, 3, a, b, c}

I attempted to remove the numbers using:

fakeList /. {x__?NumericQ, z__} -> {z}
{2, 3, a, b, c}

I expected it to grab the first three numbers but it only gets the first one. I was unable to decipher from the documentation whether BlankSequence is greedy (apparently not).

I was unable to produce a pattern test or condition to cause "z" to be non-numeric.

Help and explanation would be greatly appreciated.

$\endgroup$
4
  • 4
    $\begingroup$ See Longest $\endgroup$
    – ilian
    Commented Jul 29, 2015 at 0:24
  • $\begingroup$ graphicsList = DeleteCases[Union[Flatten[rp3D //. f_[x__] /; UnsameQ[f, List] -> {f, x}]], _?NumericQ] or graphicsList = Union[Flatten[rp3D //. f_[x__] /; UnsameQ[f, List] -> {f, x}]] /. _?NumericQ :> Sequence[] $\endgroup$
    – Bob Hanlon
    Commented Jul 29, 2015 at 0:31
  • $\begingroup$ I think pattern matching is greedy from the end of the list, so z__ matches as much as it can first, leaving x__ to match the 1. (That might not be quite right, but it has been my working principle up to now.) That's why the recommendation for using Longest[x__?NumericQ] in a previous comment. $\endgroup$
    – march
    Commented Jul 29, 2015 at 2:34
  • $\begingroup$ @march graphicsList /. {Longest[x__?NumericQ], z__} -> {z} works perfectly. Thank you $\endgroup$ Commented Jul 29, 2015 at 13:39

1 Answer 1

6
$\begingroup$

The documentation states:

If no explicit Shortest or Longest is given, ordinary expression patterns are normally effectively assumed to be Shortest[p], while string patterns are assumed to be Longest[p].

Leftmost elements in a sequence of patterns have first priority, and explicit uses of Shortest have priority over this implicit shortest behavior.

Also make sure you use RuleDelayed when working with named patterns on the right hand side unless you specifically know you want otherwise; see Unexpected behavior of rule matching a pattern.

{1, 2, 3, a, b, c} /. {Longest[__?NumericQ], z__}  :> {z}
{1, 2, 3, a, b, c} /. {__?NumericQ, Shortest[z__]} :> {z}
{1, 2, 3, a, b, c} /. {__, z__?(Not@*NumericQ)}    :> {z}
{a, b, c}

{a, b, c}

{a, b, c}
$\endgroup$
3
  • $\begingroup$ @"Mr.Wizard" Thank you. That explanation is crystal clear as to why I was experiencing the result that confused me. Thank you also for the tip on using RuleDelayed. $\endgroup$ Commented Jul 29, 2015 at 13:48
  • $\begingroup$ @"Mr.Wizard" The PatternTest to make Z non numeric was very nice. I have always skipped over reading about Composition. I viewed it as being esoteric and impractical. Nice to see it working in a real world example. I hope to add Composition to my limited Mathematica tool box. $\endgroup$ Commented Jul 29, 2015 at 14:10
  • $\begingroup$ @JackLaVigne Glad I could help! By the way beware of (1699) -- the precedence of the ? operator is highly unusual. (For more about operator precedence perhaps read (30425).) $\endgroup$
    – Mr.Wizard
    Commented Jul 29, 2015 at 17:35

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.