13

規約についての質問です。以下の 2 つのコマンド セットは、同じ結果を返します。

a = [1, 2, 3]

a.first  # => 1
a[0]     # => 1

a.last   # => 3
a[-1]    # => 3

Ruby では、明示的なインデックスと関数のどちらが優先されますか? もちろん、これが常に最初または最後の要素にアクセスするコードであると仮定します。

注:それぞれにかかるサイクルについて考えてきました。firstパラメータを受け入れるため、lastオーバーヘッドが少し増えますが、それがコミュニティの好みに影響するかどうかはわかりません。

ありがとう!


編集

この投稿のコメントを読んだ場合、私の最後の段落について大きな議論がありました. [x]が と同等であることを思い出せませんでしたが.[](x)、first と last にはもう少しオーバーヘッドがあるという私の結論は正しかったです。両方の性質を考えると、これは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)
4

3 に答える 3

11

コードは書かれるよりも読まれることが多く、特に経験の浅い Ruby プログラマーやfirstlastインデックスのセマンティクスが異なる言語を使用する人にとっては、理解するための労力が少なくて済みます。

ほとんどのプログラマーは、これらが同じであることをすぐに認識します。

a.first
a[0]

最初のほうが読みやすいです。読みにくさには大きな違いはありませんが、あります。

lastは別の問題です。インデックス 0 にアクセスすると、ほとんどすべての言語で配列の最初の要素が取得されます。ただし、負のインデックスは一部の言語でのみ使用できます。Ruby の経験がほとんどない C プログラマーが私のコードを読もうとすると、どちらが早く理解できるでしょうか?:

a.last
a[-1]

負のインデックスは、おそらく Google 検索を行うことを強いるでしょう。

于 2013-08-13T15:01:06.103 に答える
2

Matz は Ruby をいくつかの他の言語の後に設計したので、規則はそれらの他の言語から来ていると思います。

lastRuby のインスピレーションを与えた親の 1 つである Lisp では、 andメソッドに近いものを使用するため、 andは慣例firstと言えます。lastfirst

私は本当に と だけを使用firstlastます。これらの方法を使用するプログラムはたくさんありますが、最終的にはあなたの選択です。それが Ruby の美しさです ;)

于 2013-08-13T14:55:18.410 に答える
2

速度の観点から見ると、より大きなアレイの場合、firstlastは よりも高速です[]。小さい配列の場合は逆になります。

大きな配列:

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

読み書きを容易にするため、firstlastは異なり、引数なしで使用できる[]ため、より単純です。

と を使用するfirstlast、物事が簡単になることがありますが、 では困難[]ですarray.each_slice(3).map(&:first)

于 2013-08-13T15:16:09.647 に答える