用于访问数组中第一个/最后一个元素的Ruby约定
这是一个关于惯例的问题。 以下两组命令返回相同的结果。
a = [1, 2, 3] a.first # => 1 a[0] # => 1 a.last # => 3 a[-1] # => 3
在Ruby,显式索引或函数中哪些是首选的? 当然,假设这是在代码中始终访问第一个或最后一个元素。
注意:我一直在考虑每个周期都会采取的周期。 因为first
和last
接受参数,它们会有更多的开销,但我不知道这是否会影响社区的偏好。
谢谢!
编辑
如果你看过这篇文章的评论,我的最后一段就有一个很大的争论。 虽然我没记住[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)
代码的读取比编写的更多 , first
和last
需要花费较少的精力去理解,特别是对于经验不足的Ruby程序员或来自具有不同索引语义的语言的人。
虽然大多数程序员会立即知道这些是相同的:
a.first a[0]
第一个仍然更容易阅读。 阅读的难度并没有显着差异,但它就在那里。
last
是另一个问题。 访问索引0将以几乎任何语言为您提供数组的第一个元素。 但负面索引仅适用于某些语言。 如果一个具有最小Ruby经验的C程序员试图读取我的代码,那么他们会更快地理解吗?:
a.last a[-1]
负面指数可能会迫使他们进行谷歌搜索。
由于Matz在其他几种语言之后设计了Ruby,我认为这些约定来自其他语言。
在Lisp中,Ruby的一个鼓舞人心的父母,你会使用接近last
和first
方法的东西,所以我会说last
和first
是惯例。
我只是真的使用first
和last
。 我看到许多程序使用这些方法,但最终它是你的选择。 这就是Ruby的美丽;)
从速度的角度来看,对于较大的arrays, first
和last
比[]
快。 对于较小的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
为了便于编写/读取,与[]
不同,可以不带参数使用first
和last
,因此它们更简单。
有时,使用first
和last
会使事情变得更容易,而使用[]
则很困难:例如, array.each_slice(3).map(&:first)
。