# How to replace data in a list (tree) in a functional Mathematica way?

I have list containing 2D points in various groupings, i.e. points, lists of points (figures), lists of lists of points (patterns) and finally a list of patterns. The list also contains other data, i.e. Colors and other decorators.

For (a simple!) example:

fig1 = {{0,0}, {1,0}, {0,1}}
fig2 = {{2,0}, {3,0}, {2,1}}
fig3 = {{4,0}, {5,0}, {4,1}}
li = {{fig1, Red}, {{fig2, fig3}, Blue}}


Now I would like to replace the points in the list with the result of a function applied to that point, for example a matrix multiplication. For the example we can use a simple function. f[p:pnt2D] := 2p or multiplication with IdentityMatrix will do to illustrate.

I am looking for a typical functional Mathematica way to attack this problem. Extract all the points from the list, apply the function and replace with the outcome. In such a way that it works for all sorts of (huge) lists.

How to replace data in a list (tree) in a typical Mathematica way, preferably using clear code?

• Why the emphasis on "minimal code" and not "clear/efficient code", especially given that you have "all sorts of huge lists"? In any case, is this what you're looking for: li /. p : {_?NumericQ, _?NumericQ} :> f@p? – rm -rf Oct 21 '13 at 21:00
• To answer your question: huge relative to the tiny example and with minimal I probably meant clear in your vocabulary. ( English is not my native language, being precise can be difficult in a foreign language. ) – nilo de roock Oct 21 '13 at 21:05
• No worries. The reason I asked was because some users (usually new) are insistent on wanting "minimal" code solutions (to impress their boss/coworkers?) and with most tree/recursive problems, the least code is with //., which is also probably the worst in performance. Since we have that cleared up, is my second sentence the answer you were looking for? – rm -rf Oct 21 '13 at 21:11
• By comparison: I am an Android Java ( = verbose ) programmer by profession, sadly hadn't worked with Mma for a while and again I am flabbergasted by the power of the language. Sheer joy. Yes it is the answer, thanks. – nilo de roock Oct 21 '13 at 21:14
• @rm-rf well, I tried to find a duplicate question, but I could not find one. Do you think you should put an answer on record? I guess this may help people, so maybe we should not close it as too localized. I would say your solution with ReplaceAll is ideal, the question even uses the word replace in the title :). – Jacob Akkerboom Oct 21 '13 at 22:49

ReplaceAll or /. is the function you're looking for:

li /. p : {_?NumericQ, _?NumericQ} :> f@p


By restricting the 2 element list to only numeric entries, we avoid matching things like {Red, Blue}.

Here's a version using MapAll or //@:

g[p : {_?NumericQ, _?NumericQ}] := f@p
g[x_] := x

g //@ li


I'm going to suggest a slightly different form from what R.M proposed (which I voted for), in an attempt to make it a bit more robust. A list of two numeric values might occur in other parts of your expression besides your points. For example, Hue[{0.3, 0.6}] is a valid color. If you will always have a list of points we can use that to further restrict the pattern, then map the function over these lists.

Using:

li = {{fig1, Red}, {{fig2, fig3}, Hue[{0.3, 0.6}]}}


Here are two options that preserve the Hue directive:

li /. x : {{_?NumericQ, _?NumericQ} ..} :> f /@ x

li /. x_ /; ArrayQ[x, 2, NumericQ] && Dimensions[x][] == 2 :> f /@ x

{{{f[{0, 0}], f[{1, 0}], f[{0, 1}]},
RGBColor[1, 0, 0]}, {{{f[{2, 0}], f[{3, 0}], f[{2, 1}]}, {f[{4, 0}], f[{5, 0}],
f[{4, 1}]}}, Hue[{0.3, 0.6}]}}


You should compare their performance in your actual application.