13
$\begingroup$

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$
5
  • 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, 2015 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, 2015 at 15:13
  • 1
    $\begingroup$ Some possible duplicates: 78240, 46238, 70201 $\endgroup$
    – shrx
    Aug 7, 2015 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, 2015 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, 2015 at 12:34

1 Answer 1

20
$\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$
11
  • 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, 2015 at 15:16
  • 1
    $\begingroup$ @N.J.Evans valid point. Expanded. $\endgroup$
    – rcollyer
    Aug 6, 2015 at 15:20
  • 2
    $\begingroup$ …and for the kids at home, FullForm[] will help you in playing "spot the difference". :) $\endgroup$ Aug 6, 2015 at 15:21
  • 3
    $\begingroup$ @rcollyer So You are AtomQ! I was looking for you! :D $\endgroup$ Aug 6, 2015 at 15:26
  • 2
    $\begingroup$ @Guesswhoitis. no, he's on First. $\endgroup$
    – rcollyer
    Aug 6, 2015 at 15:55

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