8
$\begingroup$

Currently, I have a nested list of rules of the form

lst1={1->a,2->{3->c,4->d,5->{6->f,7->{8->h,...}}}}

(where I don't know the length of the list). I would like to apply some function z to the "first" elements of the rules to get something of the form

lst2={z[1]->a,z[2]->{z[3]->c,z[4]->d,z[5]->{z[6]->f,z[7]->{z[8]->h,...}}}}.

Here's a little bit more info about the problem:

  • I don't know the length of the (nested) list.
  • A priori, I also don't know the lengths of any of the inner lists. That means both {1->a,2->{3->c,4->d,5->{6->f,7->{8->h,...}}}} and {1->a,2->b,3->{4->d,5->{6->f,7->{8->h,...}}}} are equally possible / valid.

Basically, I want everything of the form Rule[_,_] to be mapped to Rule[z[_],_], but nothing I attempted (including Apply, MapAt, etc.) seems to work. I can't figure out the pattern matching to save my life.

One thing I thought would work is doing

lst1 /. {Rule[x_,y_]:>Rule[z[x],y]},

but this fails for inputs of the form lst3={1 -> {2 -> {3 -> {4 -> 5}}}}. For lst3 as above, I would want to get out

lst4={z[1]->{z[2]->{z[3]->{z[4]->5}}}}, 

but instead I get lst4b={z[1] -> {2 -> {3 -> {4 -> 5}}}}.

Please help!

$\endgroup$

8 Answers 8

10
$\begingroup$
list = {1 -> a, 2 -> {3 -> c, 4 -> d, 5 -> {6 -> f, 7 -> {8 -> h, 9 -> j}}}};

1. MapAt

MapAt[z, list, Append[1] /@ Position[list, _Rule]]

{z[1] -> a, z[2] -> {z[3] -> c, z[4] -> d, z[5] -> {z[6] -> f, z[7] -> {z[8] -> h, z[9] -> j}}}}

2. ReplaceAt

ReplaceAt[list, (a_ -> b_) :> z[a] -> b, Position[list, _Rule]]

{z[1] -> a, z[2] -> {z[3] -> c, z[4] -> d, z[5] -> {z[6] -> f, z[7] -> {z[8] -> h, z[9] -> j}}}}

3. Replace (a shorter variant of Syed's solution

Replace[list, (a_ -> b_) :> z[a] -> b, -1]

{z[1] -> a, z[2] -> {z[3] -> c, z[4] -> d, z[5] -> {z[6] -> f, z[7] -> {z[8] -> h, z[9] -> j}}}}

$\endgroup$
8
$\begingroup$

Using Replace / Map :

lst = {1 -> a, 2 -> {3 -> c, 4 -> d, 5 -> {6 -> f, 7 -> {8 -> h}}}};

Map[Replace[
  HoldPattern[a_ -> b_] -> z[a] -> b], lst, {1, ∞}]

EDIT

Thanks to @lericr:

Replace[lst, HoldPattern[a_ -> b_] :> z[a] -> b, Infinity]

would also work.


Result:

{z[1] -> a, z[2] -> {z[3] -> c, z[4] -> d, z[5] -> {z[6] -> f, z[7] -> {z[8] -> h}}}}

$\endgroup$
1
  • 2
    $\begingroup$ You don't need the Map, do you? Wouldn't Replace[lst, HoldPattern[a_ -> b_] :> z[a] -> b, Infinity] work? $\endgroup$
    – lericr
    Commented Nov 2, 2023 at 5:06
5
$\begingroup$

the rules to get something of the form

lst2={z[1]->a,z[2]->{z[3]->c,z[4]->d,z[5]->{z[6]->f,z[7]->{z[8]->h,...}}}}.

how about

ClearAll["Global`*"]
lst1={1->a,2->{3->c,4->d,5->{6->f,7->{8->h}}}}
lst1//.Rule[x_,y_]:>{z[x],y}
%//.{z[x_],any___}:>Rule[z[x],any]

Mathematica graphics

$\endgroup$
5
$\begingroup$

You could first find all the positions of Rule, and change the last index to 1:

lst1 = {1 -> a, 2 -> {3 -> c, 4 -> d, 5 -> {6 -> f, 7 -> {8 -> h, 9 -> j}}}}
pos = ReplacePart[Position[lst1, Rule], {_, -1} -> 1]

Then use those positions in MapAt:

MapAt[f, lst1, pos]

{f[1] -> a, f[2] -> {f[3] -> c, f[4] -> d, f[5] -> {f[6] -> f, f[7] -> {f[8] -> h, f[9] -> j}}}}

$\endgroup$
5
$\begingroup$
lst = {1 -> a, 2 -> {3 -> c, 4 -> d, 5 -> {6 -> f, 7 -> {8 -> h}}}}

lst //.  Rule[Except[_z, a_], b_] :> Rule[z @ a, b]

{z[1] -> a, z[2] -> {z[3] -> c, z[4] -> d, z[5] -> {z[6] -> f, z[7] -> {z[8] -> h}}}}

$\endgroup$
3
$\begingroup$

Additional ways to use ReplaceAll and Replace:

lst = {1 -> a, 2 -> {3 -> c, 4 -> d, 5 -> {6 -> f, 7 -> {8 -> h}}}};


lst /. Rule -> MapAt[z, 1]@*Rule

{z[1] -> a, z[2] -> {z[3] -> c, z[4] -> d, z[5] -> {z[6] -> f, z[7] -> {z[8] -> h}}}}

Replace[lst, Rule -> MapAt[z, 1]@*Rule, All, Heads -> True]

{z[1] -> a, z[2] -> {z[3] -> c, z[4] -> d, z[5] -> {z[6] -> f, z[7] -> {z[8] -> h}}}}

$\endgroup$
3
$\begingroup$

An additional way to use ReplaceAll and Cases:

list = {1 -> a, 2 -> {3 -> c, 4 -> d, 5 -> {6 -> f, 7 -> {8 -> h, 9 -> j}}}};

 # /. Cases[#, Rule[x_, y_] :> x -> z[x], ∞] &@list

{z[1] -> a, z[2] -> {z[3] -> c, z[4] -> d, z[5] -> {z[6] -> f, z[7] -> {z[8] -> h, z[9] -> j}}}}

$\endgroup$
1
$\begingroup$
list = {1 -> a, 2 -> {3 -> c, 4 -> d, 5 -> {6 -> f, 7 -> {8 -> h, 9 -> j}}}};

Using ReplacePart

With[{
  p = Append[1] /@ Position[list, _Rule],
  k = Cases[list, (x_ -> _) -> z[x], All]},
 ReplacePart[list, Thread[p -> k]]]

{z[1] -> a, z[2] -> {z[3] -> c, z[4] -> d, z[5] -> {z[6] -> f, z[7] -> {z[8] -> h, z[9] -> j}}}}

$\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.