How to improve code that quotes all array elements with `'` and returns a string containing all those quoted and comma-separated elements?
Asked Answered
P

2

11

I am using Rails 3.2.2 and I would like to quote all array elements with ' and return a string containing all those quoted and comma-separated elements. At this time I am using

['a', 'b', 'c'].collect {|x| "'#{x}'"}.join(", ")
# => "'a', 'b', 'c'"

but I think I can improve the above code (maybe by using a unknown to me Ruby method, if it exists). Is it possible?

Pigpen answered 18/5, 2012 at 5:47 Comment(5)
What you have seems good to me.Duplicator
There's nothing to optimize, bu you can use aliases: map instead of collect and * instead of join if you're starving to make your code smaller: %w[a b c].map{|x|"'#{x}'"}*', '.Hypozeugma
What happens if one of the strings in the array contains a ' by itself, e.g. ["a", "b'cd"]?Rianna
What you have is good. Also, this is pure ruby. There's nothing "rails" about it.Takishatakken
@AndrewMarshall Maybe you should convert that to an answer to make this question answered?Parapet
D
13

I use

"'#{%w{a b c}.join("', '")}'"

Here is expanded version:

' # Starting quote
%w{a b c}.join("', '") # Join array with ', ' delimiter that would give a', 'b', 'c
' # Closing quote
Daveta answered 25/12, 2012 at 16:49 Comment(3)
It appears your version performs better.Parapet
Here's why: First of all it walk array once instead of twice(map and join). Secondly it creates less ruby objects - one wrapper string for actual result and one string as a join result. Initial solution creates new array for map result and new string for each element in array. It might show worsen performance on larger array since GC would take longer.Daveta
You might want to include that in your answer to explain why your code is preferable. Also, do you mean garbage collection with 'GC'?Parapet
P
9

You can replace collect with its alias map and .join with the equivalent *. Finally, you can use the shortcut for writing an array of strings, %w(...), and you can use single quotes for the argument of .join/* as it does not use string interpolation (though it may be questionable if it preferable when it comes to performance).

%w(a b c).map {|x| "'#{x}'"} * ', '

It appears there is no performance difference between this version and the original but that that Sigurd's version is performing better:

Original  3.620000   0.000000   3.620000 (  3.632081)
This  3.640000   0.000000   3.640000 (  3.651763)
Sigurd's  2.300000   0.000000   2.300000 (  2.303195)

Code for benchmark:

require 'benchmark'

n = 1000000

Benchmark.bm do |x|
  x.report("Original") { n.times do
      ['a', 'b', 'c'].collect {|x| "'#{x}'"}.join(", ")
    end}
  x.report("This") { n.times do
      %w(a b c).map {|x| "'#{x}'"} * ', '
    end}
  x.report("Sigurd's") { n.times do
      "'#{%w{a b c}.join("', '")}'"
    end}
end
Parapet answered 25/12, 2012 at 16:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.