18

There are many ways to extract different parts of lists in Mathematica. For example, the first part of a list v can be accessed either as v[[1]] or First[v] or Take[v,1]. Likewise the last element can be accessed as v[[-1]], Last[v] or Take[v,-1]. Similarly v[[2;;]] is equivalent to Rest[v] and to Drop[v,1], and v[[;;-2]] is equivalent to Most[v] and Drop[v,-1].

The more specialized functions First, Last, Rest and Most are marginally more efficient. On the other hand, it makes sense to use the more general Part ([[ ]]) or Take/Drop if it is part of a calculation that also requires parts to be accessed that do not have a specialist function.

Beyond these considerations, are there any reasons to prefer Part over Take/Drop or the more specialized functions, other than personal preferences over coding style?

Kuba
  • 136,707
  • 13
  • 279
  • 740
Ted Ersek
  • 7,124
  • 19
  • 41

2 Answers2

21

You cannot make assignments to First, Last, Rest, or Most the way you can with Part. Therefore, there is greater consistency in using Part for all operations. See this answer for an example of and argument for this consistency.

Also, you must change functions if you need to update your code to index a different element or change an element to a Span. By using Part from the beginning you have the greatest flexibility without changing functions. This can make comparing different code revisions easier. It can also make a user defined function more flexible, e.g.: f[x_, part__ : 1] := foo @ x[[part]]

Less importantly x[[1]] is more terse than First@x, especially in the FrontEnd using 〚 〛, and I am a fan of terse coding.

Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
  • +1, for discussing the maintenance cost. – rcollyer Apr 09 '12 at 00:29
  • 6
    In a sea of brackets, x[[1]] is less comprehensible than First@x and as a result probably less maintainable, albeit one character longer :) But whilst developing x[[1]] is easier to modify. Conclusion, develop with Part and deploy with First. – image_doctor Apr 09 '12 at 08:07
  • 1
    Am the only one with Second, Third, Fourth, Fifth and Sixth defined too? :) – image_doctor Apr 09 '12 at 08:10
  • 2
    @image_doctor I find that using \[LeftDoubleBracket] and \[RightDoubleBracket] greatly helps readability compared to [[ and ]] in the frontend – acl Apr 09 '12 at 09:25
  • @acl thanks, that's definitely more compact and visually distinctive – image_doctor Apr 09 '12 at 09:34
  • @image_doctor as acl said, always use the specialized characters. I also take the controversial measure of avoiding many brackets by heavily using prefix (func @ arg) and infix (a ~func~ b). – Mr.Wizard Apr 09 '12 at 14:06
  • @acl useful, but too many characters for my taste. – rcollyer Apr 09 '12 at 15:13
  • @rcollyer you're going to confuse the newbies. :-P (newbies: \[LeftDoubleBracket] formats to in the FrontEnd; it can be entered with Esc[[Esc.) – Mr.Wizard Apr 09 '12 at 15:16
  • 7
    First/Last are so elitist. Why not FirstAmongEquals and LastButNotLeast? – Jens Apr 09 '12 at 15:20
  • @Mr.Wizard even with Esc - [[ - Esc it still requires four key strokes to two. Definitely inefficient. :) – rcollyer Apr 09 '12 at 15:22
  • @rcollyer Oh. I thought you were joking about having to type out/see the FullForm of those characters. – Mr.Wizard Apr 09 '12 at 15:37
  • @rcollyer I have them assigned to ctrl-[ and ctrl-] (and the caps lock key is ctrl on my keyboards) – acl Apr 09 '12 at 15:42
  • @acl In addition to Ctrl+[/] I use Ctrl+Alt+Shift+] for inserting 〚 〛 and placing the cursor in the middle. Do you? – Mr.Wizard Apr 09 '12 at 15:46
  • @Mr.Wizard there's also a Rain Man joke in there. – rcollyer Apr 09 '12 at 15:48
  • @Mr.Wizard No, but I should try. I just never set it up. – acl Apr 09 '12 at 16:04
  • @acl actually the key combination is Ctrl+Alt+] but I've been mashing shift needlessly, though it's not really more difficult. See http://stackoverflow.com/a/7327476/618728 – Mr.Wizard Apr 09 '12 at 16:14
  • @Mr.Wizard wrote: "... and I am a fan of terse coding... " we hadn't noticed. ;-) – nilo de roock May 08 '12 at 07:48
  • @ndroock1 Nuts! I'll redouble my efforts. – Mr.Wizard May 08 '12 at 07:59
8

Putting aside any minor performance differences, the specialized functions look cleaner and clear in intent in cases where you know for sure that you will not be needing any arbitrary part. Some examples that come to mind are

1: expression//Timing//First            (* Get only the timing *)
2: (... Sow[x]...)//Reap//Last          (* Get only sowed values *)
3: Most@#/Last@#&@CoefficientList[poly] (* normalize by coefficient of highest degree term *)
4: Rest@#/First@#&@Eigenvalues[matrix]  (* normalize by largest eigenvalue *)
5: Most@#/Rest@#&@list                  (* divide each element by the next *)

I'm not very into golfing, but I do like minimizing my keystrokes that are spent doing nothing (and avoid the mouse). If I'm at the end of a long expression and I need to take the first element, I'd simply use Part to extract it rather than move the cursor all the way back to insert a First@. In other words:

something + (insert very long expression here)[[1]]

instead of

something + First@(insert very long expression here)

If I change my mind and decide I need a different element, I have the flexibility to do so and also include all elements with [[;;]]. In such cases, you can't simply stick in a //First at the end, because of the very low precedence of Postfix — the expression returned might not be what you intended to get.

rm -rf
  • 88,781
  • 21
  • 293
  • 472
  • In the case of something + (insert very long expression here) (already bracketed as shown) you can avoid the mouse or excessive left-cursor-key by pressing: Ctrl + . + . and then left-cursor a single time. Four keystrokes total. – Mr.Wizard Apr 09 '12 at 14:11
  • @Mr.Wizard Not a very big fan of Ctrl+. — never been able to wrap my head around what it's going to select next. Of course, that might be just due to unconventional learning and a reluctance to use it, but I might get around to taming it like I did for Infix :) – rm -rf Apr 09 '12 at 14:53