string连接与Ruby中的插值

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

克里斯派恩的“学习计划”教会了我写一个像这样的基本程序…

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是一个更短的方法来做到这一点。

为什么我应该使用另一种格式有什么特别的原因?

每当TIMTOWTDI(有多种方式来做),你应该寻找利弊。 使用“string插值”(第二个)而不是“string连接”(第一个):

优点:

  • less打字
  • 自动为你调用to_s
  • 在Ruby社区中更习惯于使用
  • 在运行时更快完成

缺点:

  • 自动为你调用to_s (也许你以为你有一个string,而to_sexpression式不是你想要的,并隐藏了它不是一个string的事实)
  • 要求你使用"来分隔你的string而不是' (也许你习惯于使用' ,或者你以前用这个string来input一个string,之后才需要使用string插值)

插值和连接都有自己的优点和缺点。 下面我给出了一个基准,清楚地表明了在哪里使用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 

以下是基准testing结果

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

结论

如果string已经定义,并确保它们永远不会使用连接,否则使用插值。使用适当的将导致更好的性能比易于缩进。

@ user1181898 – 恕我直言,这是因为它更容易看到发生了什么事情。 对@ Phrogz来说,string插值会自动为你调用to_s。 作为一个初学者,你需要看看“引擎盖下”发生了什么事情,以便你学习这个概念,而不是仅仅靠死记硬背。

把它想象成学习math。 为了理解概念,你学习了“长”的方法,这样一旦你真正知道你在做什么,就可以采取捷径。 我从经验二/ B的发言我还没有先进的Ruby,但我犯了足够的错误,build议人们不该做什么。 希望这可以帮助。

如果您使用string作为缓冲区,我发现使用串联( 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.615ki/100ms String interpolate 234.274ki/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 

猜测,我会说插值生成一个临时string,这就是为什么它慢。

只是为了logging,可以同时使用双引号和单引号插入。 两者都是常规的代码。 所以:

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