Suppose:
str = "gamma blue green yellow dog cat mouse alpha beta"
Notice that str is slightly different than the example given in the question.
I've assumed that you want to replace each run of colors (or animals or letters) in the string by the word "color" (or "animals" or "letters").
Here are two ways to do that.
#1
This uses Enumerable#chunk and Object#itself. The latter was introduced in v.2.2. For earlier versions, write ...chunk { |s| s }....
str.split.map do |word|
case word
when "blue", "green", "yellow"
"color"
when "dog", "cat", "mouse"
"animal"
when "alpha", "beta", "gamma"
"letter"
end
end.chunk(&:itself).map(&:first).join(' ')
#=> "letter color animal letter"
map returns:
#=> ["letter", "color", "color", "color", "animal",
# "animal", "animal", "letter", "letter"]
which is then chunked. Denoting this array as arr, an alternative to chunking is:
arr.each_with_object([]) { |w,a| a << w if a.empty? || w != a.last }
#2
COLOR = "color"
ANIMAL = "animal"
LETTER = "letter"
h = { COLOR => %w{ blue green yellow },
ANIMAL => %w{ dog cat mouse },
LETTER => %w{ alpha beta gamma } }.
each_with_object({}) { |(k,v), h| v.each { |item| h[item] = k } }
#=> {"blue"=>"color", "green"=>"color", "yellow"=>"color",
# "dog"=>"animal", "cat"=>"animal", "mouse"=>"animal",
# "alpha"=>"letter", "beta"=>"letter", "gamma"=>"letter"}
r = /
\b # match a word break
(\w+) # match a word in capture group 1
(?:\s\1)+ # match one or more copies of the matched word, each preceded by a space
\b # match a word break
/x # extended or free-spacing mode
str.gsub(/\w+/,h).gsub(r,'\1')
#=> "letter color animal letter"
or
str.split.map { |word| h[word] }.chunk(&:itself).map(&:first).join(' ')
#=> "letter color animal letter"
str = "alpha blue beta", what is the desired result? (That is, do you want to replace a run of animals, for example, with a single "animal"?) Can the string contain words that are not animals, colors or letters (e.g., "donuts")?"blue cat green"become"color animal"or"animal color", or does it not matter? Or, do you replace only consecutive names of a kind into a word, giving you"color animal color"for"blue cat green"?