问题
This is a question about conventions. The two sets of commands below return identical results.
a = [1, 2, 3]
a.first # => 1
a[0] # => 1
a.last # => 3
a[-1] # => 3
Which of these is preferred in Ruby, the explicit index or the functions? Assuming, of course, that this is in code which always accesses the first or last element.
Note: I've been thinking about the cycles each would take. Because first and last accept parameters, they will have a little more overhead, but I don't know if that affects what the community prefers.
Thanks!
EDIT
If you read the comments on this post, there was a big debate about my last paragraph. While I failed to remember that [x] is equivalent to .[](x), I was correct in my conclusion that first and last have a bit more overhead. Considering the nature of both, I believe that this is due to the argument check for first/last. These need to check if there are arguments whereas [] can assume that they exist.
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
RESULTS
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)
回答1:
Code is read more than it is written, and first and last take less effort to understand, especially for a less experienced Ruby programmer or someone from a language with different indexing semantics.
While most programmers will immediately know that these are the same:
a.first
a[0]
the first still reads more easily. There isn't a marked difference in how hard it is to read, but it's there.
last is another issue. Accessing the index 0 will get you the first element of an array in almost any language. But negative indexing is only available in some languages. If a C programmer with minimal Ruby experience is trying to read my code, which will they understand faster?:
a.last
a[-1]
The negative index will probably force them to do a Google search.
回答2:
Since Matz designed Ruby after a few other languages, I think the conventions come from those other languages.
In Lisp, one of Ruby's inspirational parents, you would use something close to the last and first methods so I'll say last and first is convention.
I only really use first and last. I see many programs out there that use those methods but ultimately it is your choice. That's the beauty of Ruby ;)
回答3:
From the point of view of the speed, for larger arrays, first and last are faster than []. For smaller arrays it is the other way around.
Large array:
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
Small array:
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
For ease of writing/reading, first and last can be used without arguments, unlike [], so they are simpler.
Sometimes, using first and last makes things easier, while it is difficult with []: e.g., array.each_slice(3).map(&:first).
来源:https://stackoverflow.com/questions/18212240/ruby-convention-for-accessing-first-last-element-in-array