web-dev-qa-db-ja.com

Rubyでの文字列連結と補間

Ruby(初回プログラミング))を学び始めたばかりで、変数やコードのさまざまな作成方法に関する基本的な構文上の質問があります。

クリス・パインの「プログラムを学ぶ」は、このような基本的なプログラムを書くことを教えてくれました...

num_cars_again= 2
puts 'I own ' + num_cars_again.to_s + ' cars.'

これは問題ありませんが、Ruby.learncodethehardway.comのチュートリアルを偶然見つけて、このようなプログラムとまったく同じプログラムを書くように教えられました...

num_cars= 2
puts "I own #{num_cars} cars."

どちらも同じ結果を出力しますが、明らかにオプション2はそれを行うためのはるかに短い方法です。

あるフォーマットを他のフォーマットよりも使用する必要がある特別な理由はありますか?

72
Jeff H.

TIMTOWTDI(それを行う方法は複数あります)のたびに、長所と短所を探す必要があります。 「文字列連結」(1番目)の代わりに「文字列補間」(2番目)を使用します。

長所:

  • タイピングが少ない
  • to_sを自動的に呼び出します
  • Rubyコミュニティ内のより慣用的な
  • 実行時の高速化

短所:

  • 自動的にto_sを呼び出します(文字列があると思ったかもしれませんが、to_s表現は望んでいるものではなく、文字列ではないという事実を隠しています)
  • "の代わりに'を使用して文字列を区切る必要があります(おそらく'を使用する習慣があるか、それを使用して以前に文字列を入力し、後で文字列補間を使用する必要があります) )
71
Phrogz

補間と連結の両方には、独自の長所と短所があります。以下に、連結を使用する場所と補間を使用する場所を明確に示すベンチマークを示しました。

require 'benchmark'

iterations = 1_00_000
firstname = 'soundarapandian'
middlename = 'rathinasamy'
lastname = 'arumugam'

puts 'With dynamic new strings'
puts '===================================================='
5.times do
  Benchmark.bm(10) do |benchmark|
    benchmark.report('concatination') do
      iterations.times do
        'Mr. ' + firstname + middlename + lastname + ' aka soundar'
      end
    end

    benchmark.report('interpolaton') do
      iterations.times do
        "Mr. #{firstname} #{middlename} #{lastname} aka soundar"
      end
    end
  end
  puts '--------------------------------------------------'
end

puts 'With predefined strings'
puts '===================================================='
5.times do
  Benchmark.bm(10) do |benchmark|
    benchmark.report('concatination') do
      iterations.times do
        firstname + middlename + lastname
      end
    end

    benchmark.report('interpolaton') do
      iterations.times do
        "#{firstname} #{middlename} #{lastname}"
      end
    end
  end
  puts '--------------------------------------------------'
end

以下はベンチマークの結果です

Without predefined strings
====================================================
                 user     system      total        real
concatination  0.170000   0.000000   0.170000 (  0.165821)
interpolaton  0.130000   0.010000   0.140000 (  0.133665)
--------------------------------------------------
                 user     system      total        real
concatination  0.180000   0.000000   0.180000 (  0.180410)
interpolaton  0.120000   0.000000   0.120000 (  0.125051)
--------------------------------------------------
                 user     system      total        real
concatination  0.140000   0.000000   0.140000 (  0.134256)
interpolaton  0.110000   0.000000   0.110000 (  0.111427)
--------------------------------------------------
                 user     system      total        real
concatination  0.130000   0.000000   0.130000 (  0.132047)
interpolaton  0.120000   0.000000   0.120000 (  0.120443)
--------------------------------------------------
                 user     system      total        real
concatination  0.170000   0.000000   0.170000 (  0.170394)
interpolaton  0.150000   0.000000   0.150000 (  0.149601)
--------------------------------------------------
With predefined strings
====================================================
                 user     system      total        real
concatination  0.070000   0.000000   0.070000 (  0.067735)
interpolaton  0.100000   0.000000   0.100000 (  0.099335)
--------------------------------------------------
                 user     system      total        real
concatination  0.060000   0.000000   0.060000 (  0.061955)
interpolaton  0.130000   0.000000   0.130000 (  0.127011)
--------------------------------------------------
                 user     system      total        real
concatination  0.090000   0.000000   0.090000 (  0.092136)
interpolaton  0.110000   0.000000   0.110000 (  0.110224)
--------------------------------------------------
                 user     system      total        real
concatination  0.080000   0.000000   0.080000 (  0.077587)
interpolaton  0.110000   0.000000   0.110000 (  0.112975)
--------------------------------------------------
                 user     system      total        real
concatination  0.090000   0.000000   0.090000 (  0.088154)
interpolaton  0.140000   0.000000   0.140000 (  0.135349)
--------------------------------------------------

結論

文字列がすでに定義されていて、決してnilにならない場合は連結を使用し、そうでない場合は補間を使用します。インデントしやすい文字列よりもパフォーマンスが向上する適切な文字列を使用します。

8

@ user1181898-私見、それは何が起こっているのかを見るのが簡単だからです。 @Phrogzのポイントでは、文字列補間は自動的にto_sを呼び出します。初心者として、あなたは「フードの下で」何が起こっているのかを見る必要があります。

数学を学ぶようなものだと考えてください。コンセプトを理解するために「長い」方法を学び、実際に自分が何をしているのかを理解したら、ショートカットを取ることができます。私は経験から話していますb/c私はRubyでまだ高度ではありませんが、何をすべきでないかを人々にアドバイスするために十分な間違いを犯しました。

4
Martin Graham

文字列をバッファとして使用している場合、連結(String#concat)より高速に。

require 'benchmark/ips'

puts "Ruby #{Ruby_VERSION} at #{Time.now}"
puts

firstname = 'soundarapandian'
middlename = 'rathinasamy'
lastname = 'arumugam'

Benchmark.ips do |x|
    x.report("String\#<<") do |i|
        buffer = String.new

        while (i -= 1) > 0
            buffer << 'Mr. ' << firstname << middlename << lastname << ' aka soundar'
        end
    end

    x.report("String interpolate") do |i|
        buffer = String.new

        while (i -= 1) > 0
            buffer << "Mr. #{firstname} #{middlename} #{lastname} aka soundar"
        end
    end

    x.compare!
end

結果:

Ruby 2.3.1 at 2016-11-15 15:03:57 +1300

Warming up --------------------------------------
           String#<<   230.615k i/100ms
  String interpolate   234.274k i/100ms
Calculating -------------------------------------
           String#<<      2.345M (± 7.2%) i/s -     11.761M in   5.041164s
  String interpolate      1.242M (± 5.4%) i/s -      6.325M in   5.108324s

Comparison:
           String#<<:  2344530.4 i/s
  String interpolate:  1241784.9 i/s - 1.89x  slower

推測では、補間は一時的な文字列を生成すると言うので、それが遅い理由です。

2
ioquatix