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
String concatenation vs. interpolation in Ruby
提问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 theto_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#format和String#+,因为它是在红宝石施工动态字符串的所有方法,我知道
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

