# Replace heads to match a pattern

Is it possible to replace the heads to match a pattern?

eg

f[f[f[]]]    ->   a[b[c[]]]


or

f[f[], f[]]  ->   a[b[], c[]]


I looked here, but though it is related, I can't seem to apply it to this problem.

• Kinda hacky but In[76]:= heads = {a, b, c}; j = 0; ReplaceAll[f[f[f[]]], f :> (j++; heads[[j]])] Out[78]= a[b[c[]]] Commented Mar 27, 2017 at 18:53
• @DanielLichtblau that's nice - it works! Why not post as answer? Commented Mar 27, 2017 at 19:02
• Possibly related: (3585), (3858) Commented Mar 27, 2017 at 19:58
• As far as I can tell, most of the answers will also replace f if it doesn't appear as the head of an expression, e.g. f[f, f] --> a[b, c]. Is that your intention? Commented Mar 28, 2017 at 8:52
• @martin Some answers using ReplaceAll can be modified by changing /. f :> new to //. f[args___] :> new[args]. Commented Mar 28, 2017 at 10:44

replaceHeads[expr_, h_, new_] :=
(*a[b[c[]]]*)
replaceHeads[f[f[], f[]], f, {a, b, c}]
(*a[b[], c[]]*)

• nice, thanks :) Commented Mar 27, 2017 at 19:16
• This answer could be restricted to actually only matching heads by wrapping Position[...] in Cases[..., {___, 0}]. Commented Mar 28, 2017 at 9:06

Quick and dirty:

replaceHeadWithSet[expr_, h_, heads_] := Module[{j = 0},
ReplaceAll[expr,

Example:

replaceHeadWithSet[f[f[f[], f[]]], f, {a, b, c}]

(* Out[84]= a[b[c[], a[]]] *)


A different interpretation: the heads to replace are not all the same but the structure is fixed.

rep[h_@x___, {n_, r___}] := n @ rep[x, {r}]

rep[x___, {}] := x


Use:

rep[f[g[h[]]], {a, b, c}]

a[b[c[]]]

• great - thanks :) Commented Mar 27, 2017 at 20:04

Using Iterator, while it lasts:

With[{foo = GeneralUtilitiesListIterator[{a, b, c}]},
(*  a[b[c[]]]  *)


Without foo:

f[f[], f[]] /. f :> Read[#] &@GeneralUtilitiesListIterator[{a, b, c}]
(*  a[b[], c[]]  *)

Fold[Replace[#1, f[expr___] -> #2[[1]][expr], {#2[[2]]}] &, f[f[f[]]],
{{a, 0}, {b, 1}, {c, 2}}]

(* a[b[c[]]] *)


however since we are replacing all the heads iteratively at each level, the current approach will substitute the same head at every level. If you dont mind having the same head for each level then one can use the approach mentioned below

Fold[Replace[#1, f[expr___] -> #2[[1]][expr], {#2[[2]]}] &, f[f[],f[]], {{a, 0}, {b, 1}}]

(* a[b[], b[]] *)