MathGroup Archive 2003

[Date Index] [Thread Index] [Author Index]

Search the Archive

A MapLevelParts Routine

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]";

      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[].


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 

  • Prev by Date: Re: Part 2 of a recent post on Plot and v 5
  • Next by Date: Re: Why does Limit sometimes just return what I input?
  • Previous by thread: [Fwd: Re: Trigonometric math functions]
  • Next by thread: RE: A MapLevelParts Routine