       A MapLevelParts Routine

• To: mathgroup at smc.vnet.net
• Subject: [mg44604] A MapLevelParts Routine
• From: "David Park" <djmp at earthlink.net>
• Date: Mon, 17 Nov 2003 03:38:39 -0500 (EST)
• Sender: owner-wri-mathgroup at wolfram.com

```I've often wanted a routine that would map a function onto a subset of level parts in an expression without affecting the remaining level parts. I don't know of an easy way to do this with regular Mathematica functions. As far as I can tell neither MapAt nor ReplacePart will do this. At best they will map a function onto the individual pieces of a level set of parts. So I came up with the following routine.

MapLevelParts::usage =
"MapLevelParts[function, {topposition, levelpositions}][expr] will map \
the function onto the specified level positions in an expression. \
Levelpositions is a list of the selected parts. The function is applied to \
them as a group and they are replaced with a single new expression. Other \
parts not specified in levelpositions are left unchanged.\nExample:\na + b + \
c + d + e // MapLevelParts[f, {{2,4,5}}] -> a + c + f[b + d + e]";

MapLevelParts[func_,
part : {toppart___Integer?Positive,
subp : {_Integer?Positive, eprest__Integer?Positive}}][expr_] :=
Module[{work, subparts, npos, null, i, nnull = Length[{eprest}]},
work = func@Part[expr, Sequence @@ part];
newparts = {work, Table[null[i], {i, 1, nnull}]} // Flatten;
npos = Partition[Range[nnull + 1], 1];
ReplacePart[expr, newparts, subparts, npos] /. null[_] -> Sequence[]
]

The indexed nulls were necessary to keep them from combining in expressions. Try Sequence[]^2 or 2 Sequence[].

Examples:

a + b + c + d + e // MapLevelParts[f, {{2, 4, 5}}]
a + c + f[b + d + e]

a b c d e // MapLevelParts[f, {{1, 4, 5}}]
b c f[a d e]

g[a + b + c + d + e] // MapLevelParts[f, {1, {2, 4}}]
g[a + c + e + f[b + d]]

{a, b, c, d, e} // MapLevelParts[f @@ # &, {{2, 5}}]
{a, f[b, e], c, d}

Of course, these are simple examples that could be done with replacement rules. But suppose in the following expression q was actually a long expression and furthermore that it was formatted so you couldn't copy it and didn't what to type it in. Then you might not want to use a replacement rule or Collect. But you could still factor the subset of terms.

a + b/(1 + a q + b + c q + d + f q);
% // MapLevelParts[Factor, {2, 2, 1, {4, 5, 6}}]
a + b/(1 + b + d + a*q + c*q + f*q)
a + b/(1 + b + d + (a + c + f)*q)

Maybe someone can show me a simple way to do this with regular Mathematica. Otherwise I think it would be nice if Mathematica had a routine like this.

David Park