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]; subparts = Thread[{toppart, subp}]; 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 djmp at earthlink.net http://home.earthlink.net/~djmp/