3
$\begingroup$

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[2] 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?

$\endgroup$
7
  • 3
    $\begingroup$ 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? $\endgroup$
    – rm -rf
    Oct 21, 2013 at 21:00
  • $\begingroup$ 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. ) $\endgroup$ Oct 21, 2013 at 21:05
  • $\begingroup$ 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? $\endgroup$
    – rm -rf
    Oct 21, 2013 at 21:11
  • $\begingroup$ 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. $\endgroup$ Oct 21, 2013 at 21:14
  • $\begingroup$ @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 :). $\endgroup$ Oct 21, 2013 at 22:49

2 Answers 2

8
$\begingroup$

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
$\endgroup$
3
$\begingroup$

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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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