I want to replace a n-th pattern match in an expression with n. This is a very simple task, though it appears very hard to find an elegant implementation.

For example, with input

inp = {x, y, z, x, y, x, x, z}

I wish to compute, replacing pattern x,

{1, y, z, 2, y, 3, 4, z}

Preferably, I'd like to access the index n in the replacement rule. E.g. something like

Func[inp, x :> Symbol[m<>ToString@#]& ]

>>> {m1, y, z, m2, y, m3, m4, z}

How can I achieve this? It's trivial using Count and a For loop, but is very un-stylistic.


Consider using the Increment operator:

(*In[1]:= *)i = 1;

(*In[2]:= *)inp = {x, y, z, x, y, x, x, z};

(*In[3]:= *)inp /. x :> i++

(*Out[3]= {1, y, z, 2, y, 3, 4, z}*)

Hopefully it's obvious how this can be extended to your example using Symbol.

  • 4
    $\begingroup$ If you start with i=0 and then use inp /. x :> ++i, then at the end the index i contains the number of elements matched (instead of one more). Also, if you use inp /. x :> m[++i], then you get an indexing as desired (but without using Symbol, which may not be necessary). $\endgroup$ – Roman Jan 30 '20 at 21:31
  • $\begingroup$ A pity to have to use a variable, but it's still quite concise $\endgroup$ – Anti Earth Jan 31 '20 at 16:17
  • $\begingroup$ @Roman quite right, m[ind] is much more elegant, thanks! $\endgroup$ – Anti Earth Jan 31 '20 at 16:18
  • 1
    $\begingroup$ @AntiEarth with Block you can make i a local variable, so you don't need to worry about polluting the name space. $\endgroup$ – Roman Jan 31 '20 at 16:45

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.