Ruby中的字符串连接和插值

时间:2022-04-05 22:28:55

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

克里斯·派恩的“学习编程”教我写这样一个基本的程序……

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?

有什么特别的理由让我使用一种格式而不是另一种格式吗?

4 个解决方案

#1


65  

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_s for you
  • 自动为您调用to_s
  • More idiomatic within the Ruby community
  • Ruby社区中更常用的说法
  • Faster to accomplish during runtime
  • 在运行时更快地完成

Cons:

缺点:

  • Automatically calls to_s for you (maybe you thought you had a string, and the to_s representation is not what you wanted, and hides the fact that it wasn't a string)
  • 自动为您调用to_s(可能您认为您有一个字符串,而to_s表示不是您想要的,并隐藏它不是一个字符串的事实)
  • 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)
  • 要求你使用“来分隔你的字符串而不是”(也许你有使用的习惯),或者你之前用“来分隔你的字符串,之后只需要使用字符串插入)

#2


8  

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.

插值和融合都有其自身的优点和缺点。下面我给出了一个基准,它清楚地说明了在哪里使用concatination以及在哪里使用插值。

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.

如果字符串已经定义并且确定它们永远不会是nil使用concatination用插值。使用适当的一种会比容易缩进的一种性能更好。

#3


3  

@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 - IMHO,因为它更容易看到正在发生的事情。到@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中进步,但是我已经犯了很多错误,建议人们不要去做什么。希望这个有帮助。

#4


1  

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.

我猜,插值会产生一个临时字符串,这就是为什么它会变慢的原因。

#1


65  

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_s for you
  • 自动为您调用to_s
  • More idiomatic within the Ruby community
  • Ruby社区中更常用的说法
  • Faster to accomplish during runtime
  • 在运行时更快地完成

Cons:

缺点:

  • Automatically calls to_s for you (maybe you thought you had a string, and the to_s representation is not what you wanted, and hides the fact that it wasn't a string)
  • 自动为您调用to_s(可能您认为您有一个字符串,而to_s表示不是您想要的,并隐藏它不是一个字符串的事实)
  • 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)
  • 要求你使用“来分隔你的字符串而不是”(也许你有使用的习惯),或者你之前用“来分隔你的字符串,之后只需要使用字符串插入)

#2


8  

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.

插值和融合都有其自身的优点和缺点。下面我给出了一个基准,它清楚地说明了在哪里使用concatination以及在哪里使用插值。

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.

如果字符串已经定义并且确定它们永远不会是nil使用concatination用插值。使用适当的一种会比容易缩进的一种性能更好。

#3


3  

@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 - IMHO,因为它更容易看到正在发生的事情。到@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中进步,但是我已经犯了很多错误,建议人们不要去做什么。希望这个有帮助。

#4


1  

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.

我猜,插值会产生一个临时字符串,这就是为什么它会变慢的原因。