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