19

Using Ruby 1.9.3, Rails 3.2, I have the following:

"every good boy does fine".gsub("every", "all").gsub("boy", "girl").gsub("fine", "well")
# => "all good girl does well"

Is there a better way to write this? Thanks.

Victor
  • 12,632
  • 18
  • 77
  • 142

5 Answers5

22

String#gsub and Hash#fetch will be the good choice for this.

a = "every good boy does fine"
h = {"every" => "all","boy" => "girl", "fine" =>"well" }
a.gsub(/\w+/) { |m| h.fetch(m,m)}
# => "all good girl does well"

or,

a = "every good boy does fine"
h = {"every" => "all","boy" => "girl", "fine" =>"well" }
Regexp.new("^#{h.keys.join('|')}$") # => /^every|boy|fine$/
a.gsub(Regexp.new("^#{h.keys.join('|')}$"),h)
# => "all good girl does well"
Arup Rakshit
  • 113,563
  • 27
  • 250
  • 306
  • Clever use of `Regexp.union` however `'no finer boy'.gsub(Regexp.union(*h.keys),h)` -> `"no wellr girl"` – Matt Dec 18 '13 at 06:17
  • I find my original approach, though not the best, is more readable. Nevertheless, thanks for teaching. :) – Victor Dec 20 '13 at 04:13
4
replacements = [ ["every", "all"], ["boy", "girl"],["fine", "well"]
replacements.each {|replacement| str.gsub!(replacement[0], replacement[1])}

I don't know if its better, but much cleaner.

griffon vulture
  • 6,246
  • 6
  • 35
  • 56
1
subs = { "every" => "all", "boy" => "girl", "fine" => "well" }
"every good boy does fine".gsub(/\w+/) { |m| subs[m] || m }
# => 'all good girl does well'
Matt
  • 19,093
  • 1
  • 52
  • 67
1

just do this:

"every good boy does fine".gsub(/\w+/, 'every' => 'all', 'boy' => 'girl', 'fine' => 'well')

a lot easier to read :) some of the answers here to this simple question really make me wonder...lol

here's the reference: http://ruby-doc.org/core-2.1.4/String.html

gg

ah bon
  • 7,903
  • 7
  • 43
  • 86
Beckster
  • 183
  • 1
  • 5
0

If the intent is to avoid method chaining:

[9] pry(main)> "every good boy does fine".gsub("every", "all").gsub("boy", "girl").gsub("fine", "well")
=> "all good girl does well"
[10] pry(main)> "every good boy does fine".gsub(/(every)|(boy)|(fine)/) do |word|
[10] pry(main)*   case word
[10] pry(main)*   when "every"
[10] pry(main)*     "all"
[10] pry(main)*   when "boy"
[10] pry(main)*     "girl"
[10] pry(main)*   when "fine"
[10] pry(main)*     "well"
[10] pry(main)*   end
[10] pry(main)* end
=> "all good girl does well"

Alternatively:

[11] pry(main)> REPLACEMENT = { "every" => "all", "boy" => "girl", "fine" => "well"}
=> {"every"=>"all", "boy"=>"girl", "fine"=>"well"}
[12] pry(main)> "every good boy does fine".gsub(/(every)|(boy)|(fine)/) { |word| REPLACEMENT[word] }
=> "all good girl does well"
bjhaid
  • 9,342
  • 2
  • 35
  • 47