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$ 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$ 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$ 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$ Commented Jul 29, 2015 at 17:35

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.