Replacing chars in string

I am trying to globally replace characters in a string by “chaining” the
String#gsub method like so:

str = “count=(a+b); if(a<=b) d[i]=10;f(a,b)“
puts str.gsub(/,/,’ , ‘).gsub(/(/,’ ( ‘).gsub(/)/,’ )
’).gsub(/([^<>])=/,’\1 = ').gsub(/;/,”;\n”)

Is there a better (faster) way to do this ?
Here is how I want the replacement to work:

‘;’ — to be replaced by --> ‘;\n’ new line after
’,’ ------------------------> ’ , ’ single space on either side
’(’ ------------------------> ’ ( ’ single space on either side
’)’ ------------------------> ’ ) ’ single space on either side
’=’ ------------------------> ’ = ’ single space on either side except when
preceded by < or >

I am using ruby 1.7.3 (2002-11-17) [i386-mswin32]

TIA,
-shanko

For your need, the chained gsub is the fasted I can think of. Here’s my
comparison against two solutions involving the block form of gsub.

I’m using ruby 1.7.3 (2002-11-27) [i586-linux].

require ‘benchmark’
include Benchmark

n = 1000
str = “count=(a+b); if(a<=b) d[i]=10;f(a,b)”
test = nil
bm do |x|
x.report( “chained gsubs:” ) do
n.times do
test = str.gsub(/,/,’ , ‘).gsub(/(/,’ ( ‘).gsub(/)/,’ ) ‘).gsub(/([^<>])=/,’\1 = ').gsub(/;/,“;\n”)
end
# puts
# p test
end
x.report( “grouped gsub:” ) do
n.times do
test = str.gsub( /(?:(,|(|)|[^<>]=)|(;))/ ) do
if $1
"#{ $1[0…-2] } #{ $1[-1,1] } "
else
“#{ $2 }\n”
end
end
end
# puts
# p test
end
x.report( “gsub and case:” ) do
n.times do
test = str.gsub( /[,();]|[^<>]=/ ) do |m|
case m
when /=$/
"#{ $` } = "
when /;/
“;\n”
else
" #{ m } "
end
end
end
# puts
# p test
end
end

Benchmark results:

                  user     system      total        real

chained gsubs: 0.830000 0.000000 0.830000 ( 0.831508)
grouped gsub: 2.020000 0.000000 2.020000 ( 2.022475)
gsub and case: 1.270000 0.000000 1.270000 ( 1.277238)

_why

···

Shashank Date (sdate@kc.rr.com) wrote:

I am trying to globally replace characters in a string by “chaining” the
String#gsub method like so:

str = “count=(a+b); if(a<=b) d[i]=10;f(a,b)”
puts str.gsub(/,/,’ , ‘).gsub(/(/,’ ( ‘).gsub(/)/,’ )
‘).gsub(/([^<>])=/,’\1 = ').gsub(/;/,“;\n”)

Is there a better (faster) way to do this ?

Hi,

n = 1000
str = “count=(a+b); if(a<=b) d[i]=10;f(a,b)”
test = nil
bm do |x|
x.report( “chained gsubs:” ) do
n.times do
test = str.gsub(/,/,’ , ‘).gsub(/(/,’ ( ‘).gsub(/)/,’ ) ‘).gsub(/([^<>])=/,’\1 = ‘).gsub(/;/,“;\n”)
end
# puts
# p test
end
x.report( “chained gsubs 2:” ) do
n.times do
test = str.gsub(/[,()]/,’ & ‘).gsub(/([^<>])=/,’\1 = ').gsub(/;/,“;\n”)
end
# puts
# p test
end

With 10,000 iterations:

                  user     system      total        real

chained gsubs: 2.270000 0.020000 2.290000 ( 2.306303)
chained gsubs 2: 2.030000 0.040000 2.070000 ( 2.066607)
grouped gsub: 5.570000 0.060000 5.630000 ( 5.758734)
gsub and case: 3.720000 0.070000 3.790000 ( 3.950212)

···

At Wed, 11 Dec 2002 14:58:28 +0900, why the lucky stiff wrote:


Nobu Nakada

x.report( “chained gsubs 3:” ) do
n.times do
test = str.gsub(/[,()]/,’ & ‘).gsub!(/([^<>])=/,’\1 = ').gsub!(/;/,“;\n”)
end
# puts
# p test
end

:slight_smile: With 100,000 iterations:

  		 user     	system      	total        	real

chained gsubs: 6.270000 0.020000 6.290000 ( 6.389039)
chained gsubs 2: 5.760000 0.020000 5.780000 ( 5.808392)
chained gsubs 3: 5.620000 0.000000 5.620000 ( 5.703204)
grouped gsub: 19.880000 0.020000 19.900000 ( 20.185286)
gsub and case: 12.580000 0.020000 12.600000 ( 12.791412)

···

On Wed, Dec 11, 2002 at 03:18:05PM +0900, nobu.nokada@softhome.net wrote:

Hi,

At Wed, 11 Dec 2002 14:58:28 +0900, > why the lucky stiff wrote:

n = 1000
str = “count=(a+b); if(a<=b) d[i]=10;f(a,b)”
test = nil
bm do |x|
x.report( “chained gsubs:” ) do
n.times do
test = str.gsub(/,/,’ , ‘).gsub(/(/,’ ( ‘).gsub(/)/,’ ) ‘).gsub(/([^<>])=/,’\1 = ‘).gsub(/;/,“;\n”)
end
# puts
# p test
end
x.report( “chained gsubs 2:” ) do
n.times do
test = str.gsub(/[,()]/,’ & ‘).gsub(/([^<>])=/,’\1 = ').gsub(/;/,“;\n”)
end
# puts
# p test
end

With 10,000 iterations:

                  user     system      total        real

chained gsubs: 2.270000 0.020000 2.290000 ( 2.306303)
chained gsubs 2: 2.030000 0.040000 2.070000 ( 2.066607)
grouped gsub: 5.570000 0.060000 5.630000 ( 5.758734)
gsub and case: 3.720000 0.070000 3.790000 ( 3.950212)


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

/*

  • Please skip to the bottom of this file if you ate lunch recently
    
  •                         -- Alan
    

*/
– from Linux kernel pre-2.1.91-1

Hi,

···

At Wed, 11 Dec 2002 18:52:14 +0900, Mauricio Fernández wrote:

x.report( “chained gsubs 3:” ) do
n.times do
test = str.gsub(/[,()]/,’ & ‘).gsub!(/([^<>])=/,’\1 = ').gsub!(/;/,“;\n”)
end
# puts
# p test
end

You’d better to separate it to 2 lines:

  (test = str.gsub(/[,()]/,' \& ')).gsub!(/([^<>])=/,'\1 = ')
  test.gsub!(/;/,";\n")  


Nobu Nakada