Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Is there some equivalence of MapIndexed for rules?

Consider a substitution on

3 a + 4 b + 21 c + ....

The first integer I want to replace by 1, the second integer by 4, and the i'th integer by i^2.

1 a + 4 b + 9 c  + ....

How would you do that? I imagine some kind of indexed replacement would be useful.

Addition:I would like to use it to replace expressions like f[a]@f[b]@f[c]@...@f[X] with f[1]@f[2]@f[3]@...@f[n]

share|improve this question

7 Answers 7

up vote 11 down vote accepted

Here is a simple approach,

index = 0
1 a + 2 b + 4 c + 10 f /.  b_?IntegerQ :> (++index)^2

Unlikely to do as you expect, but I'll mention it as it does work in some situations.

Note for one thing you lose the '1' as it is simplified out before substitution

share|improve this answer
2  
You beat me by four seconds. :-) –  Mr.Wizard Sep 24 '12 at 17:52

If we assume that the integers that you wish to replace are on the first level as in the example, then a good equivalent for MapIndexed is... MapIndexed! The second argument does not need to be a list:

$eqn = 3 a + 4 b + 21 c;

MapIndexed[#1 /. _Integer :> #2[[1]]^2 &, $eqn]

(* a + 4 b + 9 c *)
share|improve this answer

Though it is not purely functional I often find it easiest to simply use a temporary variable for incrementing in a replacement:

Module[{i = 1},
 3 a + 4 b + 21 c /. n_Integer :> i++^2
]
a + 4 b + 9 c

A couple of answers are assuming that you want to increment the counter for each object at level one, rather than for each appearance of an integer. This is an important distinction. Consider:

expr = 3 a^2 + b + 21 c;

Module[{i = 1}, expr /. n_Integer :> i++^2]
a^4 + b + 9 c

If instead you prefer operate on coefficients including the implicit 1 for b you might consider tools like CoefficientRules for your manipulation:

CoefficientRules[expr]

MapIndexed[# -> #2[[1]]^2 &, %[[All, 1]]]

FromCoefficientRules[%, Variables@expr]
{{2, 0, 0} -> 3, {0, 1, 0} -> 1, {0, 0, 1} -> 21}

{{2, 0, 0} -> 1, {0, 1, 0} -> 4, {0, 0, 1} -> 9}

a^2 + 4 b + 9 c
share|improve this answer
    
I was trying to fix the issue with the lack of an integer. The first attempt, while not fixing it does give an amusing result: Module[{i = 1}, expr /. (n_.) s_Symbol :> i++^2 s]. Removing Symbol does not do the job, either, but the result isn't nearly as cool. I need to play with it to see if it is doable with replacement rules. In the meantime, the first result is infinitely more opaque if you forget the s on the RHS. –  rcollyer Sep 24 '12 at 20:59

Here's an approach that uses a more explicit rule replacement:

MapIndexed[{##} /.
   {coeff_ sym_ | sym_, {index_}} :> index^2 sym &,
 expr]
share|improve this answer

Ah well, watch dis (which will end in tears if you do not provide the structure mentioned by @R.M):

i = 1;
3 a + 4 b + 21 c + 30 d + 15 e /. Times[a_, b_] :> (i++)^2 b
a + 4 b + 9 c + 16 d + 25 e

Regarding your additional request:

i = 1;
f[a]@f[b]@f[c]@f[d] /. f[a_] :> f[i++]
f[1][f[2][f[3][f[4]]]]
share|improve this answer

Assuming your expression is of the form given in the question and that it is ordered in the sense of OrderedQ, then a simple way to replace the numbers would be:

Dot[Range[Length@#]^2, #] &@Last@GatherBy[Level[3 a + 4 b + 21 c, {-1}], Head]
(* a + 4 b + 9 c *)

To break it down further, Level[3 a + 4 b + 21 c, {-1}] gives you the leaves of the expression (or loosely speaking, the individual components sans the head), which is {3, a, 4, b, 21, c}. Then it is collected according to their heads using GatherBy, and Integer comes before Symbol. Finally, the integers are discarded and replaced with the square of the indices and then the expression is reconstructed.

share|improve this answer
Range[ Length @ #]^2 . Last /@ List @@ # &[3 a + 4 b + 21 c + 30 d + 15 e]
a + 4 b + 9 c + 16 d + 25 e

or

List @@ #[[All, 2]].(Range @ Length @ #)^2 & [ 3 a + 4 b + 21 c + 30 d + 15 e]
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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