2004-12-19

Mathematica -- smart programming without loops

Ralf:
My question is, how it would be possible to avoid the for loop in order to apply a function to all values of Y in a array of tuples {{X1,Y2},{X2,Y2}, {...},...
thus creating a new array of tuples with new calculated Y-values.


Well...
(in further text, I'll assume that l has the list in question, and f is the function you want applied. For example
--> l = {{5, 3}, {2, 8}, {1, 0}, {2, 3}}
--> f@x_:=2x+3
  1. First, a simulated loop:
    --> MapAt[f, l, {i, 2}~Table~{i, Length@l}]

    Here Table constructs loop indices, and MapAt uses them to apply f. The most straightforward solution, directly translated from the loop
    one.
  2. A solution that you probably want:
    --> l /. {x_, y_} :> {x, f@y}
    This uses pattern matching, and it most clearly communicates your intention. Also, for this one you don't have to define f... just write 2y+3 or whatever you want instead of f@y.
    But, if you search for completely general solution, this is not it. The problem is that, if l has exactly two elements, pattern matching will do the wrong thing. Although, maybe your list ("array", as you call it) will never have exactly two elements, and then it will be fine.
  3. Kludge for the previous one.
    If you really like the previous one, but can't use it because you
    can't guarantee that Length@l!=2, you can use
    --> # /. {x_, y_} :> {x, f@y} & /@ l
    as a kludge. It works in all cases, but it's slightly more convoluted.
  4. The Mathematica way:
    How a Mathematica apprentice would probably solve it.
    --> Transpose@MapAt[f /@ # &, Transpose@l, 2]
    First you transpose l to get all Ys together. Then you map f to them (MapAt 2), and transpose back.
  5. A bizzare one:
    Just to be different (and shorter:).
    If you really want to hide what exactly you do in that part of code. :-)
    --> Inner[#1@#2&,{#&,f},#,{}[[0]]]&/@l
  6. Of course, if you want the result to end up in the same list
    variable (l), just prepend "l=" to any of these solutions.




Anyway all of these solutions are much shorter than my elaborate "For-loop" construct.


I believe that. :-) For-loops are sooo old fashioned (NHF). They are
in Mma for(:) the same reasons that eg. goto is in Pascal - backward
compatibility, if you really want it. In fact, Mma also has a Goto.
I suppose you wouldn't use that.:-)

(Except if you want to do something REALLY bizarre, like I did in this post. :-D It's in Croatian, but if you have no translator around, just look at the end of post. There is a BASIC program written in Mma - with Let, Goto, Gosub, Dim, Print, and stuff - if you still remember those things.)

must miss something more than the final square bracket


O, no. Never. :-)
I might miss an ordinary parenthesis (as I did in my previous mail, opened before "in further text") in writing mails, but bracket in Mma code - no way. ;-)

Read it better. There are three closed brackets right after "0" (but
just two right before it). I know it's weird, but that solution was supposed to be weird. ;->

Ok thanks a lot and I might come back to you during the term.


Just one little warning: if you do, send me small pieces of code (there can be a lot of them, but keep them small) - like this one would probably be, just if you remembered to really attach it:-p. I'm talking from experience, for your own good... if you send me a big chunk of code, I'll optimize it in such a way that you might not recognize it. ;-) Not to mention keying in my solution, five rows full of #&/@{}[[0]]s . :-o

Nema komentara:

Objavi komentar