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$
  • 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$ – Daniel Lichtblau 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$ – Martin Ender 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$
  • $\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$ – Martin Ender 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$
  • $\begingroup$ great - thanks :) $\endgroup$ – martin Mar 27 '17 at 20:04
4
$\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.