用于访问数组中第一个/最后一个元素的Ruby约定

这是一个关于惯例的问题。 以下两组命令返回相同的结果。

a = [1, 2, 3] a.first # => 1 a[0] # => 1 a.last # => 3 a[-1] # => 3 

在Ruby,显式索引或函数中哪些是首选的? 当然,假设这是在代码中始终访问第一个或最后一个元素。

注意:我一直在考虑每个周期都会采取的周期。 因为firstlast接受参数,它们会有更多的开销,但我不知道这是否会影响社区的偏好。

谢谢!


编辑

如果你看过这篇文章的评论,我的最后一段就有一个很大的争论。 虽然我没记住[x]相当于.[](x) ,但我的结论是正确的,即第一个和最后一个有更多的开销。 考虑到两者的性质,我认为这是由于first / last的参数检查。 这些需要检查是否存在参数,而[]可以假设它们存在。

 require 'benchmark' a = [1..1000] MAX = 1000000 Benchmark.bm(15) do |b| b.report("small first") { MAX.times do; a.first; end } b.report("small [0]") { MAX.times do; a[0]; end } b.report("small last") { MAX.times do; a.last; end } b.report("small [-1]") { MAX.times do; a[-1]; end } end a = [1..100000000000] Benchmark.bm(15) do |b| b.report("large first") { MAX.times do; a.first; end } b.report("large [0]") { MAX.times do; a[0]; end } b.report("large last") { MAX.times do; a.last; end } b.report("large [-1]") { MAX.times do; a[-1]; end } end 

结果

  user system total real small first 0.350000 0.000000 0.350000 ( 0.901497) small [0] 0.330000 0.010000 0.340000 ( 0.857786) small last 0.370000 0.000000 0.370000 ( 1.054216) small [-1] 0.370000 0.000000 0.370000 ( 1.137655) user system total real large first 0.340000 0.010000 0.350000 ( 0.897581) large [0] 0.320000 0.010000 0.330000 ( 0.889725) large last 0.350000 0.000000 0.350000 ( 1.071135) large [-1] 0.380000 0.000000 0.380000 ( 1.119587) 

代码的读取比编写的更多firstlast需要花费较少的精力去理解,特别是对于经验不足的Ruby程序员或来自具有不同索引语义的语言的人。

虽然大多数程序员会立即知道这些是相同的:

 a.first a[0] 

第一个仍然更容易阅读。 阅读的难度并没有显着差异,但它就在那里。

last是另一个问题。 访问索引0将以几乎任何语言为您提供数组的第一个元素。 但负面索引仅适用于某些语言。 如果一个具有最小Ruby经验的C程序员试图读取我的代码,那么他们会更快地理解吗?:

 a.last a[-1] 

负面指数可能会迫使他们进行谷歌搜索。

由于Matz在其他几种语言之后设计了Ruby,我认为这些约定来自其他语言。

在Lisp中,Ruby的一个鼓舞人心的父母,你会使用接近lastfirst方法的东西,所以我会说lastfirst是惯例。

我只是真的使用firstlast 。 我看到许多程序使用这些方法,但最终它是你的选择。 这就是Ruby的美丽;)

从速度的角度来看,对于较大的arrays, firstlast[]快。 对于较小的arrays,它是另一种方式。

大arrays:

 array = (0..100000000).to_a t = Time.now 10.times{array[0]} puts Time.now - t # => 0.000225356 t = Time.now 10.times{array.first} puts Time.now - t # => 2.9736e-05 t = Time.now 10.times{array[-1]} puts Time.now - t # => 7.847e-06 t = Time.now 10.times{array.last} puts Time.now - t # => 6.174e-06 

小arrays:

 array = (0..100).to_a t = Time.now 10.times{array[0]} puts Time.now - t # => 4.403e-06 t = Time.now 10.times{array.first} puts Time.now - t # => 5.933e-06 t = Time.now 10.times{array[-1]} puts Time.now - t # => 4.982e-06 t = Time.now 10.times{array.last} puts Time.now - t # => 5.411e-06 

为了便于编写/读取,与[]不同,可以不带参数使用firstlast ,因此它们更简单。

有时,使用firstlast会使事情变得更容易,而使用[]则很困难:例如, array.each_slice(3).map(&:first)