在
Ternary operator年,一个想加入[“foo”,“bar”,“baz”]的人用逗号和“和”引用
The Ruby Cookbook说
If efficiency is important to you,
don’t build a new string when you can
append items onto an existing string.
[And so on]… Use str << var1 << ‘ ‘
<< var2 instead.
但是这本书是在2006年写的.
在Ruby的所有主要实现中,使用附加(即<<)仍然是构建一个较小字符串数组的大字符串的最快方式.
解决方法
可以使用Array#join,而String#<<当你不能. 使用String#的问题是它必须创建一个中间(不需要的)字符串对象,而String#<<突变原始字符串.以下是通过Array#join,String#和String#连接1000个字符串的时间结果(以秒为单位),“,”1,000次.
Ruby 1.9.2p180 user system total real Array#join 0.320000 0.000000 0.320000 ( 0.330224) String#+ 1 7.730000 0.200000 7.930000 ( 8.373900) String#+ 2 4.670000 0.600000 5.270000 ( 5.546633) String#<< 1 1.260000 0.010000 1.270000 ( 1.315991) String#<< 2 1.600000 0.020000 1.620000 ( 1.793415) JRuby 1.6.1 user system total real Array#join 0.185000 0.000000 0.185000 ( 0.185000) String#+ 1 9.118000 0.000000 9.118000 ( 9.118000) String#+ 2 4.544000 0.000000 4.544000 ( 4.544000) String#<< 1 0.865000 0.000000 0.865000 ( 0.866000) String#<< 2 0.852000 0.000000 0.852000 ( 0.852000) Ruby 1.8.7p334 user system total real Array#join 0.290000 0.010000 0.300000 ( 0.305367) String#+ 1 7.620000 0.060000 7.680000 ( 7.682265) String#+ 2 4.820000 0.130000 4.950000 ( 4.957258) String#<< 1 1.290000 0.010000 1.300000 ( 1.304764) String#<< 2 1.350000 0.010000 1.360000 ( 1.347226) Rubinius (head) user system total real Array#join 0.864054 0.008001 0.872055 ( 0.870757) String#+ 1 9.636602 0.076005 9.712607 ( 9.714820) String#+ 2 6.456403 0.064004 6.520407 ( 6.521633) String#<< 1 2.196138 0.016001 2.212139 ( 2.212564) String#<< 2 2.176136 0.012001 2.188137 ( 2.186298)
以下是基准代码:
WORDS = (1..1000).map{ rand(10000).to_s } N = 1000 require 'benchmark' Benchmark.bmbm do |x| x.report("Array#join"){ N.times{ s = WORDS.join(',') } } x.report("String#+ 1"){ N.times{ s = WORDS.first WORDS[1..-1].each{ |w| s += ","; s += w } } } x.report("String#+ 2"){ N.times{ s = WORDS.first WORDS[1..-1].each{ |w| s += "," + w } } } x.report("String#<< 1"){ N.times{ s = WORDS.first.dup WORDS[1..-1].each{ |w| s << ","; s << w } } } x.report("String#<< 2"){ N.times{ s = WORDS.first.dup WORDS[1..-1].each{ |w| s << "," << w } } } end
Ubuntu在RVM下获得的结果. Ruby上的RubyInstaller的Ruby 1.9.2p180的结果与上述1.9.2类似.