Конкатенация строк и интерполяция в Ruby


Я только начинаю изучать Ruby (first time programming), и у меня есть основной синтаксический вопрос относительно переменных и различных способов написания кода.

Крис Пайн "учись программировать" научил меня писать подобные программы...

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-это гораздо более короткий способ сделать это.

есть ли какая-то особая причина, почему я должен использовать одного формата над другим?

4 69

4 ответа:

всякий раз, когда TIMTOWTDI (есть более чем один способ сделать это), вы должны искать плюсы и минусы. Использование" Строковой интерполяции "(второй) вместо "конкатенации строк" (первый):

плюсы:

  • меньше ввода
  • автоматически называет to_s для вас
  • более идиоматично в сообществе Ruby
  • быстрее выполнить во время время работы

плюсы:

  • автоматически называет to_s для вас (может быть, вы думали, что у вас есть строка, и to_s представление-это не то, что вы хотели, и скрывает тот факт, что это была не строка)
  • требует, чтобы вы использовать " чтобы разделить строку вместо ' (возможно, у вас есть привычка использовать ', или вы ранее набрали строку с помощью этого и только позже необходимо использовать строку интерполяция)

и интерполяция, и конкатинация имеют свою силу и слабость. Ниже я дал Эталон, который четко демонстрирует, где использовать конкатинацию и где использовать интерполяцию.

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)
--------------------------------------------------

вывод

Если строки уже определены и уверены, что они никогда не будут равны нулю, используйте конкатинацию, иначе используйте интерполяцию.Используйте соответствующий, который приведет к лучшей производительности, чем один который легко отступить.

@user1181898-IMHO, это потому, что легче увидеть, что происходит. К точке @Phrogz, строка интерполяции автоматически вызывает to_s для вас. Как новичок, вам нужно увидеть, что происходит "под капотом", чтобы вы изучили концепцию, а не просто учились наизусть.

подумайте об этом, как изучение математики. Вы изучаете "длинный" путь, чтобы понять концепции, чтобы вы могли срезать путь, как только вы действительно знаете, что делаете. Я говорю из опыта b / c я еще не настолько продвинулся в Ruby, но я сделал достаточно ошибок, чтобы советовать людям, что не делать. Надеюсь, это поможет.

Если вы используете строку в качестве буфера, я обнаружил, что с помощью конкатенации (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

на предположение, я бы сказал, что интерполяция генерирует временную строку, поэтому она медленнее.