在
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类似.