5

I'm new to use the amazing map function in Mathematica, and I've found it really elegant to program in simple lines of code. However, I'd like to perform more elegant stuff. I've found this question, but its not what I'm trying to achieve. How do I use Map for a function with two arguments?

I want to apply a two, or more, argument function using columns of a list as arguments

My approach is the following:

For an arbitrary list:

vector = Table[   {RandomReal[], RandomReal[], RandomReal[]}, {n, 0, 10} ]

enter image description here

I want to apply the Tan[] using two columns as an arguments, so I tried unsuccessfully writing:

Tan[#1/#2] & {vector[[;; , {1, 2}]]}

enter image description here

I know I can use Table[] (in a for loop way) like this to achieve my solution:

Table[{ Tan[vector[[n, 2]]/vector[[n, 1]]]}, {n, 1, Length[vector]}] 

enter image description here

However, I'd like to master the functional programming style. How can I achieve the same output using Map(/@)

Any tutorial/book/lecture would be greatly appreciated as well.

Thanks!

Joshua Salazar
  • 733
  • 4
  • 12
  • 2
    Tan[#1/#2] & @@@ vector[[;; , {1, 2}]] would do it; see manual: @@@ means "apply at level 1". Alternatively, Tan[#[[1]]/#[[2]]] & /@ vector. Maybe invert #[[1]] and #[[2]] – I'm unsure as to which one you want. – Roman Apr 05 '22 at 16:30
  • 1
    Also Tan[vector[[All,2]]/vector[[All,1]]] – user1066 Apr 05 '22 at 21:21

2 Answers2

13

Since you're looking to learn more about functional style, I'll elaborate rather than just provide an answer.

We start with our table:

vector = Table[{RandomReal[], RandomReal[], RandomReal[]}, {n, 0, 10}]

We could either re-structure the table first, or deal with selecting which elements to apply the Tan function to later. If we restructure first, I'd actually prefer the following to what you had (vector2 is there just so I can easily refer to this later).

vector2 = vector[[All, 1 ;; 2]]

Now, let's consider several ways to map. It's often easier to get a feel for these things by using undefined symbols in your mapping expression. So, compare what you get with these:

f /@ vector
(*gives something like {f[{0.408218, 0.315962, 0.472218}], ...}*)

f /@ vector2 (gives something like {f[{0.408218, 0.315962}], ...})

f @@@ vector ({f[0.408218, 0.315962, 0.472218], ...})

f @@@ vector2 ({f[0.408218, 0.315962]})

Map[f, vector, {-2}] ({f[{0.408218, 0.315962, 0.472218}]})

etc

That last form for Map is nice when it's easier to figure out where to apply a function from the "bottom" up in a structure, but in this case it's equivalent to one of the previous forms, because your structure isn't very deep.

Let's pick this expression: f @@@ vector2. At this point, you could define your anonymous function like you did: Tan[#1/#2] &, to give this:

Tan[#1/#2] & @@@ vector2

(or alternatively, since vector2 was just convenience:) Tan[#1/#2] & @@@ vector[[All, 1 ;; 2]]

But, another nice thing that is often seen in a functional style is function composition. Since we already have the functions you need, specifically Divide and Tan, you don't need the Slot version. You could just do this:

Tan@*Divide @@@ vector[[All, 1 ;; 2]]

I'm not suggestion that this is better. Sometimes it's clearer/cleaner.

Now, if we had chosen this to start: f /@ vector, then we would need to use Part to extract the elements from the list:

Tan[#[[1]]/#[[2]]] & /@ vector
lericr
  • 27,668
  • 1
  • 18
  • 64
4

One way would be to use Inner:

Inner[Times,vector,{1,1,1},Tan[#2/#1]&]

(* {0.328928, 0.0877953, -1.11698, 0.163536, 8.47242, -1.30076, -0.876783, -0.445995,

3.10856, 13.781, -0.0637223} *)

To join the result to vector, creating a new column:

result=Join[vector,Transpose[{Inner[Times,vector,{1,1,1},Tan[#2/#1]&]}],2]

$$\left( \begin{array}{cccc} 0.923193 & 0.293373 & 0.28368 & 0.328928 \\ 0.563943 & 0.0493849 & 0.29899 & 0.0877953 \\ 0.0540691 & 0.464139 & 0.238681 & -1.11698 \\ 0.965447 & 0.1565 & 0.083503 & 0.163536 \\ 0.139205 & 0.639633 & 0.73339 & 8.47242 \\ 0.291075 & 0.647993 & 0.45214 & -1.30076 \\ 0.157494 & 0.381412 & 0.516915 & -0.876783 \\ 0.15384 & 0.418765 & 0.603784 & -0.445995 \\ 0.682685 & 0.859883 & 0.08333 & 3.10856 \\ 0.523494 & 0.784382 & 0.919915 & 13.781 \\ 0.0527971 & 0.991843 & 0.757848 & -0.0637223 \\ \end{array} \right)$$

where:

vector = Table[{RandomReal[], RandomReal[], RandomReal[]}, {n, 0, 10}]

$$\left( \begin{array}{ccc} 0.923193 & 0.293373 & 0.28368 \\ 0.563943 & 0.0493849 & 0.29899 \\ 0.0540691 & 0.464139 & 0.238681 \\ 0.965447 & 0.1565 & 0.083503 \\ 0.139205 & 0.639633 & 0.73339 \\ 0.291075 & 0.647993 & 0.45214 \\ 0.157494 & 0.381412 & 0.516915 \\ 0.15384 & 0.418765 & 0.603784 \\ 0.682685 & 0.859883 & 0.08333 \\ 0.523494 & 0.784382 & 0.919915 \\ 0.0527971 & 0.991843 & 0.757848 \\ \end{array} \right)$$

user1066
  • 17,923
  • 3
  • 31
  • 49