<?xml version="1.0" encoding="UTF-8"?>
<code>
  <code>@wordsToHighlight=["important","monkey","dancing"]
def highlightText(input)
  for i in 0..@wordsToHighlight.length-1 do
    input = input.gsub(@wordsToHighlight[i],"*" + @wordsToHighlight[i] + "*")
  end
  return input
end</code>
  <comment>Here is the 5th edition of Rubyize this. You can find the original blog post on ruby fleebie here : http://www.rubyfleebie.com/rubyize-this-5th-edition/

Tom wrote a very simple ruby script to highlight some words in a text. He chose to highlight the words with asterisks, like *that* (In 2 months, perhaps Tom will have to use his script to produce HTML output or something else... he will be screwed with those basic asterisks). Tom has absolutely no ruby background, help him refactor his code &lt;em&gt;ala&lt;/em&gt; Ruby, that is : short, clean and simple.

By the way, Tom didn't put a lot of effort in his algorithm. His dumb gsub thing will mistakenly replace &lt;em&gt;parts of words&lt;/em&gt; instead of whole words only. Maybe some improvements would be needed there.</comment>
  <created-at type="datetime">2008-01-03T13:33:19+00:00</created-at>
  <id type="integer">203</id>
  <language>Ruby</language>
  <permalink>rubyize-this-5th-edition</permalink>
  <refactors-count type="integer">16</refactors-count>
  <title>Rubyize this : 5th edition</title>
  <trackback-url>http://www.rubyfleebie.com/rubyize-this-5th-edition/trackback</trackback-url>
  <updated-at type="datetime">2008-09-16T14:49:29+00:00</updated-at>
  <user-id type="integer">184</user-id>
  <refactors type="array">
    <refactor>
      <code>def highlight_text(input, words_to_highlight=%w(important monkey dancing))
  input.gsub(/#{words_to_highlight.join('|')}/i, '*\0*')
end

puts highlight_text("Hey monkey, it's important you start dancing right now!")
# &gt;&gt; Hey *monkey*, it's *important* you start *dancing* right now!

</code>
      <code-id type="integer">203</code-id>
      <comment>Here's my take, it's short but not perfect</comment>
      <created-at type="datetime">2008-01-03T14:26:58+00:00</created-at>
      <id type="integer">1339</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer">1</user-id>
      <user-name>macournoyer</user-name>
      <user-website>http://macournoyer.com</user-website>
    </refactor>
    <refactor>
      <code>def highlight_text(input, words_to_highlight = [], wrapper = '*\1*')
  input.gsub(/\b(#{words_to_highlight.join("|")})\b/, wrapper)
end</code>
      <code-id type="integer">203</code-id>
      <comment></comment>
      <created-at type="datetime">2008-01-03T14:33:15+00:00</created-at>
      <id type="integer">1341</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer">368</user-id>
      <user-name>mvanholstyn</user-name>
      <user-website nil="true"></user-website>
    </refactor>
    <refactor>
      <code>def highlightText(input, open_tag, close_tag)
  input.split(/ /).collect {|word| @wordsToHighlight.include?(word) ? "#{open_tag}#{word}#{close_tag}" : word }.join(" ")
end

input = "The world of very important things contained many monkeys that really liked dancing around!"
p highlightText(input, "&lt;b&gt;", "&lt;/b&gt;")</code>
      <code-id type="integer">203</code-id>
      <comment>this dumbass ajax form is not working!</comment>
      <created-at type="datetime">2008-01-03T14:34:33+00:00</created-at>
      <id type="integer">1342</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Jason</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code>def highlightText(input, open_tag, close_tag, words_to_highlight)
  input.split(/ /).collect {|word| words_to_highlight.include?(word) ? "#{open_tag}#{word}#{close_tag}" : word }.join(" ")
end

list_of_words=["important","monkey","dancing"]
input = "The world of very important things contained many monkeys that really liked dancing around!"
p highlightText(input, "&lt;b&gt;", "&lt;/b&gt;", list_of_words)</code>
      <code-id type="integer">203</code-id>
      <comment>Revision 2, this time passing in list of words to highlight as a function argument like macournoyer did (first reply), which is much better than accessing a named variable outside of the function.</comment>
      <created-at type="datetime">2008-01-03T14:38:59+00:00</created-at>
      <id type="integer">1343</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Jason</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code></code>
      <code-id type="integer">203</code-id>
      <comment>Sorry about the form not working Jason, should be fixed now</comment>
      <created-at type="datetime">2008-01-03T14:41:38+00:00</created-at>
      <id type="integer">1344</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer">1</user-id>
      <user-name>macournoyer</user-name>
      <user-website>http://macournoyer.com</user-website>
    </refactor>
    <refactor>
      <code>class String
  def hilight(marker = '*', *args)
    gsub(/\b(#{args.join('|')})\b/, "#{marker}\\1#{marker}")
  end
end

words = %w(monkeys dancing important)
input = "The world of very important things contained many monkeys that really liked dancing around!"
input.hilight('*', *words)
</code>
      <code-id type="integer">203</code-id>
      <comment>Good solutions above. This is overkill, but can't think of anything else that hasn't already been done.</comment>
      <created-at type="datetime">2008-01-03T15:15:19+00:00</created-at>
      <id type="integer">1345</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Justin Jones</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code>class Highlighter

  def initialize(keywords, prefix='*', suffix='*', delimiter=' ')
    @keywords, @prefix, @suffix, @delimiter = keywords, prefix, suffix, delimiter
  end

  def highlight(text)
    text.split(@delimiter).collect do |word|
      @keywords.include?(word) ? highlight_word(word) : word
    end.join(@delimiter)
  end

  private

  def highlight_word(word)
    @prefix + word + @suffix
  end

end

highlighter = Highlighter.new %w(important monkey dancing)

text = "there are some very important monkeys dancing the most important of all dances in monkey land"
highlighted_text = highlighter.highlight(text)

puts "ORIGINAL   : #{text}"
puts "HIGHLIGHTED: #{highlighted_text}"


</code>
      <code-id type="integer">203</code-id>
      <comment>i purposely wrote this without looking at the refactorings... funny how close it still is but it's a bit different.  a little more verbose imo but extensible.  the only issue i have with it is that you are limited to one a single delimiter.</comment>
      <created-at type="datetime">2008-01-03T17:24:23+00:00</created-at>
      <id type="integer">1346</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer">210</user-id>
      <user-name>Jason Dew</user-name>
      <user-website>http://jasondew.com</user-website>
    </refactor>
    <refactor>
      <code>class String
  def pad(char = ' ')
    "#{char}#{self}#{char}"
  end

  def highlight(marker = '*', *args)
    gsub(/\b(#{args.join('|')})\b/) { |word| word.pad(marker) }
  end
end

words = %w(monkeys dancing important)
input = "The world of very important things contained many monkeys that really liked dancing around!"

input.highlight('*', *words)</code>
      <code-id type="integer">203</code-id>
      <comment>I'm sure the String#pad (not sure about the name either) utility function added here is available somewhere, but anyways. Also using the block version of gsub this time.</comment>
      <created-at type="datetime">2008-01-03T20:05:11+00:00</created-at>
      <id type="integer">1347</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Justin Jones</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code>def highlight_text words_to_highlight, fore="*", after="*" 
	self.split.each do |token| 
		if words_to_highlight =~ token
			STDOUT &lt;&lt; "#{fore} #{$&amp;} #{after} "
		else
			STDOUT &lt;&lt; "#{token} "
		end
	end
end

line = "This is an important text about a dancing monkey"
line.highlight_text %r{important|dancing|monkey}, "&lt;b&gt;", "&lt;/b&gt;"
gets</code>
      <code-id type="integer">203</code-id>
      <comment>There are already better versions here</comment>
      <created-at type="datetime">2008-01-06T14:27:24+00:00</created-at>
      <id type="integer">1376</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Jens Ruzicka</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code>def highlight_text(input, words=%w(important monkey dancing), sym='*')  
  input.gsub(/\b(#{words.join("|")})\b/i, "#{sym}\\1#{sym}")
end


puts highlight_text("This is the Important text to highlight. Can you see the dancing monkey-wrench?")

</code>
      <code-id type="integer">203</code-id>
      <comment>Nothing major here, just made it case insensitive. An issue I have is that hyphenated words like "monkey-wrench" will still get highlighted and I have no idea how to get the regexp to ignore words beginning or ending with a -.</comment>
      <created-at type="datetime">2008-01-07T13:51:55+00:00</created-at>
      <id type="integer">1397</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>David Madden</user-name>
      <user-website>http://moose56.com</user-website>
    </refactor>
    <refactor>
      <code>class String
  def highlight(mark='*')
    mark+self+mark
  end
end

class Sentence
  attr_writer :words_to_highlight
  def initialize(string='')
    @string = string
    @words_to_highlight = %w()
  end
  def highlight(words_to_highlight=@words_to_highlight,mark='*')
    all_words = @string.split(/\b/)
    highlighted = all_words.collect do |word| 
      ( words_to_highlight.include?(word) ) ? word.highlight : word
    end
    highlighted.join()
  end
  def to_s
    @string
  end
end

sentence = Sentence.new("hello world, whats happening?")
puts sentence
puts sentence.highlight(%w(world whats))
sentence.words_to_highlight = %w(world)
puts sentence.highlight

</code>
      <code-id type="integer">203</code-id>
      <comment>Probably went overboard.</comment>
      <created-at type="datetime">2008-01-09T04:55:16+00:00</created-at>
      <id type="integer">1427</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Mike</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code>class String
  def highlight(words=%w(), mark='*')
    if ( self.split(/\b/).length == 1 )
      words.include?(self) ? mark+self+mark : self
    else
      self.split(/\b/).collect { |w| w.highlight(words) }.join
    end
  end
end

puts "hello world, what's up?".highlight(%w(hello up))</code>
      <code-id type="integer">203</code-id>
      <comment>another one, neither of these work on contractions, this one features recursion and only involves modifying string.

This one outputs: 
*hello* world, what's *up*?

</comment>
      <created-at type="datetime">2008-01-09T05:07:49+00:00</created-at>
      <id type="integer">1428</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Mike</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code>class String
  def highlight(words=%w(), mark='*')
    if ( self.split(/\b/).length == 1 )
      words.include?(self) ? mark+self+mark : self
    else
      self.split(/\b/).collect { |w| w.highlight(words, mark) }.join
    end
  end
end

puts "hello world, what's up?".highlight(%w(hello up), '+')</code>
      <code-id type="integer">203</code-id>
      <comment>found a bug in that one, didnt work when you had a full sentence and passed in a mark.

This one will correctly output +hello+ world, what's +up+?

I'm going to stop now, sorry for the triple post.</comment>
      <created-at type="datetime">2008-01-09T05:11:22+00:00</created-at>
      <id type="integer">1429</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Mike</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code>class String
  def highlight(words = nil, mark = "*")
    words.nil? ? self : self.gsub(/#{words.join("|")}/) {|s| "#{mark}#{s}#{mark}"}
  end
end

puts "A very important list is in monkey dancing tonight with pants down in rain today.".highlight %w(monkey dancing today)</code>
      <code-id type="integer">203</code-id>
      <comment>How i did it.</comment>
      <created-at type="datetime">2008-01-09T23:43:30+00:00</created-at>
      <id type="integer">1449</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Simon Gate</user-name>
      <user-website></user-website>
    </refactor>
    <refactor>
      <code>@wordsToHighlight=["important","monkey","dancing"]

def highlightText(input)
  input.gsub(Regexp.union(*@wordsToHighlight), '*\0*')
end

puts highlightText("I think it's important to have a dancing monkey in your bedroom.")
# =&gt; I think it's *important* to have a *dancing* *monkey* in your bedroom.</code>
      <code-id type="integer">203</code-id>
      <comment>Regexp.union is your friend!  This also demonstrates a typical use of the splat operator to turn an array into an argument list, and the usage of back-references in global substitutions.  One thing that I found recently is that your replacement string needs to be in single-quotes or Ruby will turn your \0,\1, etc references into the corresponding ASCII characters instead of the backreferences!  If you use a double-quoted string, \\0, \\1  etc. should accomplish the same thing.</comment>
      <created-at type="datetime">2008-01-26T18:11:48+00:00</created-at>
      <id type="integer">1772</id>
      <language>Ruby</language>
      <rating type="integer">0</rating>
      <ratings-count type="integer">0</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Sean Cribbs</user-name>
      <user-website>http://seancribbs.com</user-website>
    </refactor>
    <refactor>
      <code>class String
  def highlight(words=[])
    words.empty? ? self : self.gsub(Regexp.union(*words), '*\0*')
  end
end

puts "I think it's important to have a dancing monkey in your bedroom.".highlight %w(important monkey dancing)
# =&gt; I think it's *important* to have a *dancing* *monkey* in your bedroom.</code>
      <code-id type="integer">203</code-id>
      <comment>Now having read some of the others, I'll borrow from Simon's idea:</comment>
      <created-at type="datetime">2008-01-26T18:16:31+00:00</created-at>
      <id type="integer">1774</id>
      <language>Ruby</language>
      <rating type="integer">5</rating>
      <ratings-count type="integer">1</ratings-count>
      <title>On Rubyize this : 5th edition</title>
      <user-id type="integer" nil="true"></user-id>
      <user-name>Sean Cribbs</user-name>
      <user-website>http://seancribbs.com</user-website>
    </refactor>
  </refactors>
</code>
