5
$\begingroup$

I want to replace all occurences of the symbol x with x[a], as long as it is not in the form x[a].

In other words, I am looking for magicReplacementRule in

x[a] + x /. magicReplacementRule
--> x[a] + x[a]

I tried

x[a] + x /. Except[x[a], x] -> x[a]

but the result was x[a][a] + x[a].

$\endgroup$
4
  • $\begingroup$ Replace[x[a] + x, x -> y, {1}]? $\endgroup$
    – kglr
    Commented Nov 12, 2014 at 21:07
  • 1
    $\begingroup$ ... also x[a] + x /. {x -> y, z : _[_] :> z}? $\endgroup$
    – kglr
    Commented Nov 12, 2014 at 21:13
  • 3
    $\begingroup$ How about x[a] + x /. {x[a] -> x[a], x -> x[a]} $\endgroup$
    – Greg Hurst
    Commented Nov 12, 2014 at 21:23
  • $\begingroup$ @ChipHurst: Yes, that of course works. I feel sufficiently foolish now. (I think I had tried {x[a] -> x, x -> x[a]}, which was nonsense.) $\endgroup$ Commented Nov 12, 2014 at 21:29

3 Answers 3

11
$\begingroup$

Use Replace instead of ReplaceAll with the option Heads -> False.

Replace[x[a] + x, x -> y, {0, Infinity}, Heads -> False]

{0, Infinity} here is a level specification which tells Replace to replace everywhere, just like ReplaceAll. You can drop Heads -> False because it's the default setting for Replace, but I wanted to point out the option which controls this behaviour.


Update: It appears that since version 10, All can be used as a substitute for the {0, Infinity} level specification:

Replace[x[a] + x, x -> y, All]
$\endgroup$
4
  • 1
    $\begingroup$ You can use -1 instead of Infinity in lvl specs, especially if you're concerned about character count. $\endgroup$
    – rcollyer
    Commented Nov 12, 2014 at 22:05
  • 1
    $\begingroup$ @rcollyer When I read this, I thought: wouldn't it be easier to just have a level specification All that stands for {0, Infinity}? It turns out it works, but I don't see it documented anywhere. $\endgroup$
    – Szabolcs
    Commented Nov 12, 2014 at 22:26
  • $\begingroup$ You might be right. I'll hunt for it, too. $\endgroup$
    – rcollyer
    Commented Nov 12, 2014 at 22:59
  • $\begingroup$ @rcollyer Just tried in 8 and 9. It seems this is new in v10. Only tested it in Level and Replace. Perhaps it doesn't yet work in all function that take level specifications. $\endgroup$
    – Szabolcs
    Commented Nov 12, 2014 at 23:24
2
$\begingroup$

In the depth-first preorder traversal of ReplaceAll complete expressions are matched before heads therefore one can use a skip rule(1)(2). Since you also want to replace x with x[a], the pattern to be skipped, you can use a single rule with Alternatives:

{x[a], x} /. x[a] | x -> x[a]
{x[a], x[a]}

( Since Plus[x[a], x[a]] evaluates to 2 x[a] I used List in the example above. )

$\endgroup$
4
  • $\begingroup$ I often use expr /. {pat -> pat, old -> new} -- explicitly here expr /. {x[a] -> x[a], x-> x[a]} -- but Alternatives works here since pat and new are the same. +1 $\endgroup$
    – Michael E2
    Commented Jun 4, 2015 at 3:00
  • $\begingroup$ @MichaelE2 Do you have an answer where this "skip rule" features prominently? I'll add it to my superscript links above. $\endgroup$
    – Mr.Wizard
    Commented Jun 4, 2015 at 3:24
  • 1
    $\begingroup$ Sorry, nothing turns up. I think I've used it on this site. Unfortunately, Cases[SemanticImport["MSE", "CodeBlock"], {p_ -> p_, __}, Infinity] does not do what I want. :) $\endgroup$
    – Michael E2
    Commented Jun 4, 2015 at 3:45
  • $\begingroup$ @Michael While looking for another example I realized this question is a duplicate. :-/ $\endgroup$
    – Mr.Wizard
    Commented Jun 4, 2015 at 14:44
1
$\begingroup$

because the x you want to replace is in the last level of the expression you can use:

Replace[Sin[x] + x[a] + x, x -> y, {-1}]
    (*y + Sin[y] + x[a]*)
$\endgroup$

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