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$ Mar 27 '17 at 18:53
  • $\begingroup$ @DanielLichtblau that's nice - it works! Why not post as answer? $\endgroup$
    – martin
    Mar 27 '17 at 19:02
  • $\begingroup$ Possibly related: (3585), (3858) $\endgroup$
    – Mr.Wizard
    Mar 27 '17 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$ Mar 28 '17 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
    Mar 28 '17 at 10:44
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
    Mar 27 '17 at 19:16
  • $\begingroup$ This answer could be restricted to actually only matching heads by wrapping Position[...] in Cases[..., {___, 0}]. $\endgroup$ Mar 28 '17 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
    Mar 27 '17 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, privacy policy and cookie policy

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