I am looking for a more elegant way of concatenating strings in Ruby.
I have the following line:
source = \"#{ROOT_DIR}/\" << project <<
Here are more ways to do this:
"String1" + "String2"
"#{String1} #{String2}"
String1<<String2
And so on ...
Here's another benchmark inspired by this gist. It compares concatenation (+
), appending (<<
) and interpolation (#{}
) for dynamic and predefined strings.
require 'benchmark'
# we will need the CAPTION and FORMAT constants:
include Benchmark
count = 100_000
puts "Dynamic strings"
Benchmark.benchmark(CAPTION, 7, FORMAT) do |bm|
bm.report("concat") { count.times { 11.to_s + '/' + 12.to_s } }
bm.report("append") { count.times { 11.to_s << '/' << 12.to_s } }
bm.report("interp") { count.times { "#{11}/#{12}" } }
end
puts "\nPredefined strings"
s11 = "11"
s12 = "12"
Benchmark.benchmark(CAPTION, 7, FORMAT) do |bm|
bm.report("concat") { count.times { s11 + '/' + s12 } }
bm.report("append") { count.times { s11 << '/' << s12 } }
bm.report("interp") { count.times { "#{s11}/#{s12}" } }
end
output:
Dynamic strings
user system total real
concat 0.050000 0.000000 0.050000 ( 0.047770)
append 0.040000 0.000000 0.040000 ( 0.042724)
interp 0.050000 0.000000 0.050000 ( 0.051736)
Predefined strings
user system total real
concat 0.030000 0.000000 0.030000 ( 0.024888)
append 0.020000 0.000000 0.020000 ( 0.023373)
interp 3.160000 0.160000 3.320000 ( 3.311253)
Conclusion: interpolation in MRI is heavy.
Situation matters, for example:
# this will not work
output = ''
Users.all.each do |user|
output + "#{user.email}\n"
end
# the output will be ''
puts output
# this will do the job
output = ''
Users.all.each do |user|
output << "#{user.email}\n"
end
# will get the desired output
puts output
In the first example, concatenating with +
operator will not update the output
object,however, in the second example, the <<
operator will update the output
object with each iteration. So, for the above type of situation, <<
is better.
You may use +
or <<
operator, but in ruby .concat
function is the most preferable one, as it is much faster than other operators. You can use it like.
source = "#{ROOT_DIR}/".concat(project.concat("/App.config"))
You can concatenate in string definition directly:
nombre_apellido = "#{customer['first_name']} #{customer['last_name']} #{order_id}"
Concatenation you say? How about #concat
method then?
a = 'foo'
a.object_id #=> some number
a.concat 'bar' #=> foobar
a.object_id #=> same as before -- string a remains the same object
In all fairness, concat
is aliased as <<
.