Ruby 中的字符串连接与插值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10076579/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 04:59:42  来源:igfitidea点击:

String concatenation vs. interpolation in Ruby

rubystring-concatenationstring-interpolation

提问by Jeff H.

I am just starting to learn Ruby (first time programming), and have a basic syntactical question with regards to variables, and various ways of writing code.

我刚刚开始学习 Ruby(第一次编程),并且对变量和编写代码的各种方式有一个基本的语法问题。

Chris Pine's "Learn to Program" taught me to write a basic program like this...

Chris Pine 的“Learn to Program”教我写一个像这样的基本程序......

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

This is fine, but then I stumbled across the tutorial on ruby.learncodethehardway.com, and was taught to write the same exact program like this...

这很好,但后来我偶然发现了 ruby​​.learncodethehardway.com 上的教程,并被教导编写与这样完全相同的程序......

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

They both output the same thing, but obviously option 2 is a much shorter way to do it.

它们都输出相同的内容,但显然选项 2 是一种更短的方法。

Is there any particular reason why I should use one format over the other?

为什么我应该使用一种格式而不是另一种格式?

采纳答案by Phrogz

Whenever TIMTOWTDI (there is more than one way to do it), you should look for the pros and cons. Using "string interpolation" (the second) instead of "string concatenation" (the first):

每当 TIMTOWTDI(有不止一种方法可以做到)时,您都应该寻找利弊。使用“字符串插值”(第二个)而不是“字符串连接”(第一个):

Pros:

优点:

  • Is less typing
  • Automatically calls to_sfor you
  • More idiomatic within the Ruby community
  • Faster to accomplish during runtime
  • 打字少
  • 自动呼叫to_s
  • 在 Ruby 社区中更加惯用
  • 在运行时更快地完成

Cons:

缺点:

  • Automatically calls to_sfor you (maybe you thought you had a string, and the to_srepresentation is not what you wanted, and hides the fact that it wasn't a string)
  • Requires you to use "to delimit your string instead of '(perhaps you have a habit of using ', or you previously typed a string using that and only later needed to use string interpolation)
  • 自动呼叫to_s您(可能您认为您有一个字符串,而to_s表示不是您想要的,并隐藏了它不是字符串的事实)
  • 要求您使用"来分隔您的字符串而不是'(也许您有使用的习惯',或者您之前使用它键入了一个字符串,后来才需要使用字符串插值)

回答by Soundar Rathinasamy

Both interpolation and concatination has its own strength and weakness. Below I gave a benchmark which clearly demonstrates where to use concatination and where to use interpolation.

插值和串联都有自己的优点和缺点。下面我给出了一个基准,它清楚地展示了在哪里使用串联以及在哪里使用插值。

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

And below is the Benchmark result

以下是基准测试结果

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

Conclusion

结论

If strings already defined and sure they will never be nil use concatination else use interpolation.Use appropriate one which will result in better performance than one which is easy to indent.

如果已经定义了字符串并且确定它们永远不会为零,则使用串联,否则使用插值。使用适当的字符串会比易于缩进的字符串具有更好的性能。

回答by Martin Graham

@user1181898 - IMHO, it's because it's easier to see what's happening. To @Phrogz's point, string interpolation automatically calls the to_s for you. As a beginner, you need to see what's happening "under the hood" so that you learn the concept as opposed to just learning by rote.

@ user1181898 - 恕我直言,这是因为更容易看到正在发生的事情。对于@Phrogz 的观点,字符串插值会自动为您调用 to_s。作为初学者,您需要了解“幕后”发生的事情,以便您了解概念,而不仅仅是死记硬背。

Think of it like learning mathematics. You learn the "long" way in order to understand the concepts so that you can take shortcuts once you actually know what you are doing. I speak from experience b/c I'm not that advanced in Ruby yet, but I've made enough mistakes to advise people on what not to do. Hope this helps.

把它想象成学习数学。你学习“长”的方法是为了理解概念,这样一旦你真正知道你在做什么,你就可以走捷径。我是根据经验 b/c 说的,我在 Ruby 方面还没有那么先进,但是我犯了足够多的错误来建议人们不要做什么。希望这可以帮助。

回答by ioquatix

If you are using a string as a buffer, I found that using concatenation (String#concat) to be faster.

如果您使用字符串作为缓冲区,我发现使用连接 ( 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

Results:

结果:

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

At a guess, I'd say that interpolation generates a temporary string which is why it's slower.

猜测一下,我会说插值会生成一个临时字符串,这就是它变慢的原因。

回答by mpospelov

Here is a full benchmark which also compares Kernel#formatand String#+as it's all methods for construction dynamic string in ruby that I know

这是一个完整的基准,这也比Kernel#formatString#+,因为它是在红宝石施工动态字符串的所有方法,我知道

require 'benchmark/ips'

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

FORMAT_STR = 'Mr. %<firstname>s %<middlename>s %<lastname>s aka soundar'
Benchmark.ips do |x|
  x.report("String\#<<") do |i|
    str = String.new
    str << 'Mr. ' << firstname << ' ' << middlename << ' ' << lastname << ' aka soundar'
  end

  x.report "String\#+" do
    'Mr. ' + firstname + ' ' + middlename + ' ' + lastname + ' aka soundar'
  end

  x.report "format" do
    format(FORMAT_STR, firstname: firstname, middlename: middlename, lastname: lastname)
  end

  x.report("String interpolate") do |i|
    "Mr. #{firstname} #{middlename} #{lastname} aka soundar"
  end

  x.compare!
end

And results for ruby 2.6.5

以及 ruby​​ 2.6.5 的结果

Warming up --------------------------------------
           String#<<
    94.597k i/100ms
            String#+    75.512k i/100ms
              format    73.269k i/100ms
  String interpolate   164.005k i/100ms
Calculating -------------------------------------
           String#<<     91.385B (±16.9%) i/s -    315.981B
            String#+    905.389k (± 4.2%) i/s -      4.531M in   5.013725s
              format    865.746k (± 4.5%) i/s -      4.323M in   5.004103s
  String interpolate    161.694B (±11.3%) i/s -    503.542B

Comparison:
  String interpolate: 161693621120.0 i/s
           String#<<: 91385051886.2 i/s - 1.77x  slower
            String#+:   905388.7 i/s - 178590.27x  slower
              format:   865745.8 i/s - 186768.00x  slower