13
$\begingroup$

This question already has an answer here:

So much thanks to Szabolcs in improving sequence.. for complete explanation. I am so glad to read all explanation which fundamentally remove the problem. But in number 4 of its explanation pointed to Apply in {1} level: As we show with @@@. But I have a problem with this function. As Szabolcs pointed, this function acts as:

list = {{x1,y1}, {x2,y2}, ..., {xn,yn}}, 
 f@@@list= {f[x1,y1], f[x2,y2], ..., f[xn,yn]}

But for example we want to use Last for a list as:

m = {{1, 2, I}, {0, 0, 0}, {I, I, 3}, {2, 6, I}, {0, 0, 0}, {0, 0, 0}, {1, 6, 4}, {0, 0, 0}, {1, 4, 5}}


Last@m

{1, 4, 5}


Apply[Last, {m}]= Last@@{m}

{1, 4, 5}

Last /@ m
{I, 0, 3, I, 0, 0, 4, 0, 5}

But Apply[Last, {m}, {1}] or Last@@@{m} doesn't have any result. I predicted that I should have Last@@@ {m}={Last{1, 2, I},Last{0,0,0},....} which is the result of Last/@ m.

Also I can't understand what is the exact differnce between Last@m and Last@@{m}. I have confused with these syntax.

$\endgroup$

marked as duplicate by shrx, Jens, Mr.Wizard Aug 7 '15 at 6:01

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 1
    $\begingroup$ @@@ supplies a sequence to the function being applied, with n slots where n is the length of the sublists you're mapping over. Last takes a list as an argument, so you need Last/@m, for understanding, the way to make @@@ work is to do Last[List@##]&@@@m, but that's just tearing the list apart and putting it back together. $\endgroup$ – N.J.Evans Aug 6 '15 at 15:10
  • $\begingroup$ Notice the difference in Szabolcs explanation of @@@ and f/@{{x1,y1},{x2,y2}}, which gives {f[{x1,y1}],f[{x2,y2}]} $\endgroup$ – N.J.Evans Aug 6 '15 at 15:13
  • 1
    $\begingroup$ Some possible duplicates: 78240, 46238, 70201 $\endgroup$ – shrx Aug 7 '15 at 5:26
  • 1
    $\begingroup$ Actually many operations can be phrased either in terms of Apply or Map. I should have mentioned in my answer that Map tends to be quite a bit faster than Apply. I still use Apply a lot in the exact same way I described, but for the times when performance is important, you should know that Apply tends not to be as fast as Map. $\endgroup$ – Szabolcs Aug 7 '15 at 8:56
  • 1
    $\begingroup$ To stir the pot a little, MapThread[f,{a,b}]===f@@@Transpose[{a,b}] when a and b are lists of equal length. I mentally think of MapThread as zipWith from Haskell. $\endgroup$ – Reb.Cabin Aug 7 '15 at 12:34
21
$\begingroup$

I know this has been answered already on this site, but I cannot seem to find it.

Map and Apply do subtly different things. For example,

Map[f, {a,b,c}]
(* {f[a], f[b], f[c]} *)

If you have a list that is more deeply nested, without using the third argument which is for level specification, you get

Map[f, {{a,b}, {c}}]
(* {f[{a,b}], f[{c}]} *)

or, if you do use it

Map[f, {{a, b}, {c}}, 2]
(* {f[{f[a], f[b]}], f[{f[c]}]} *)
Map[f, {{a, b}, {c}}, {1,2}]
(* {f[{f[a], f[b]}], f[{f[c]}]} *)
Map[f, {{a, b}, {c}}, {2}]
(* {{f[a], f[b]}, {f[c]}} *)

But, in every case, Map applies f to each element as is.

Apply does not do that; it explicitly replaces the Head of the element with f, as follows:

Apply[f, bob[a]] (* f @@ bob[a] *)
(* f[a] *)
Apply[f, {{a, b}, {c}}, {1}] (* f @@@ {{a, b}, {c}} *)
(* {f[a, b], f[c]} *)
Apply[f, {{a, b}, {c}}, {0, 1}]
(* f[f[a, b], f[c]] *)

On the surface, these look a lot like the results from Map, but the key difference is Apply does not work on something that is AtomQ as they are effectively headless (except in special cases), e.g.

Through[{AtomQ, ValueQ}[a]]
(* {True, False} *)
f @@ a
(* a *)
f @@@ {a}
(* {a} *)

For your application, you have nested lists, and to see how those are interpreted, use FullForm, e.g.

FullForm@{{1, 2, I}, {0, 0, 0}}
(* List[List[1, 2, Complex[0, 1]], List[0, 0, 0]] *)

(As an aside, note how I is interpreted as Complex[0,1], but despite this, AtomQ@Complex[0,1] returns True.)

So, you want to use Map, e.g.

Last /@ {{1, 2, I}, {0, 0, 0}}
(* {I, 0} *)

because @@@ will replace the heads of the inner lists with Last, e.g.

f @@@ {{1, 2, I}, {0, 0, 0}} (* where f is standing in for Last *)
(* {f[1, 2, I], f[0, 0, 0]} *)
$\endgroup$
  • 2
    $\begingroup$ Since this is aimed at mid-level new users, it might be useful to point out that when Apply is used on a list of lists, List itself is a head and that {...} is just shorthand. I think people often overlook until the first time they're really confronted with it, like this. +1 $\endgroup$ – N.J.Evans Aug 6 '15 at 15:16
  • 1
    $\begingroup$ @N.J.Evans valid point. Expanded. $\endgroup$ – rcollyer Aug 6 '15 at 15:20
  • 2
    $\begingroup$ …and for the kids at home, FullForm[] will help you in playing "spot the difference". :) $\endgroup$ – J. M. will be back soon Aug 6 '15 at 15:21
  • 3
    $\begingroup$ @rcollyer So You are AtomQ! I was looking for you! :D $\endgroup$ – Dr. belisarius Aug 6 '15 at 15:26
  • 2
    $\begingroup$ @Guesswhoitis. no, he's on First. $\endgroup$ – rcollyer Aug 6 '15 at 15:55

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