10
$\begingroup$

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.

$\endgroup$
7
  • 3
    $\begingroup$ Kinda hacky but In[76]:= heads = {a, b, c}; j = 0; ReplaceAll[f[f[f[]]], f :> (j++; heads[[j]])] Out[78]= a[b[c[]]] $\endgroup$ Commented Mar 27, 2017 at 18:53
  • $\begingroup$ @DanielLichtblau that's nice - it works! Why not post as answer? $\endgroup$
    – martin
    Commented Mar 27, 2017 at 19:02
  • $\begingroup$ Possibly related: (3585), (3858) $\endgroup$
    – Mr.Wizard
    Commented Mar 27, 2017 at 19:58
  • 1
    $\begingroup$ 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? $\endgroup$ Commented Mar 28, 2017 at 8:52
  • 1
    $\begingroup$ @martin Some answers using ReplaceAll can be modified by changing /. f :> new to //. f[args___] :> new[args]. $\endgroup$
    – Michael E2
    Commented Mar 28, 2017 at 10:44

5 Answers 5

12
$\begingroup$
replaceHeads[expr_, h_, new_] := 
 ReplacePart[expr, Thread[Position[expr, h] -> new]]
replaceHeads[f[f[f[]]], f, {a, b, c}]
(*a[b[c[]]]*)
replaceHeads[f[f[], f[]], f, {a, b, c}]
(*a[b[], c[]]*)
$\endgroup$
2
  • $\begingroup$ nice, thanks :) $\endgroup$
    – martin
    Commented Mar 27, 2017 at 19:16
  • $\begingroup$ This answer could be restricted to actually only matching heads by wrapping Position[...] in Cases[..., {___, 0}]. $\endgroup$ Commented Mar 28, 2017 at 9:06
6
$\begingroup$

Quick and dirty:

replaceHeadWithSet[expr_, h_, heads_] := Module[{j = 0},
  ReplaceAll[expr, 
   h :> (j = Mod[j + 1, Length[heads], 1]; heads[[j]])]]

Example:

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

(* Out[84]= a[b[c[], a[]]] *)
$\endgroup$
5
$\begingroup$

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[]]]
$\endgroup$
1
  • $\begingroup$ great - thanks :) $\endgroup$
    – martin
    Commented Mar 27, 2017 at 20:04
5
$\begingroup$

Using Iterator, while it lasts:

With[{foo = GeneralUtilities`ListIterator[{a, b, c}]},
 f[f[f[]]] /. f :> Read[foo]]
(*  a[b[c[]]]  *)

Without foo:

f[f[], f[]] /. f :> Read[#] &@GeneralUtilities`ListIterator[{a, b, c}]
(*  a[b[], c[]]  *)
$\endgroup$
2
$\begingroup$
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[]] *)
$\endgroup$

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.