From: Ryan Davis Date: 2011-03-18T17:15:08+09:00 Subject: Re: matching a word in any number of characters > I have need of some code to match any of a number of words in any number > of characters from the beginning of the word between the smallest number > of characters that will uniquely identify it and the total number of > characters in the word. My solution so far has been a set of kind of > ugly, but conceptually simple, regular expressions: There is nothing "kind of ugly" about it and it doesn't "work fine". The regexps are _very_ ugly and as you can see below, they're ugly enough that it is hard to see that they're wrong and fit to match a lot more than they should. I edit one step at a time and describe each step above the method. # original - flog: 35.1 def expand_attribute_arg1(attr) if attr.to_s.downcase.match( /^s[t]?[r]?[e]?[n]?[g]?[t]?[h]?$/ ) return 'Strength' elsif attr.to_s.downcase.match( /^d[e]?[x]?[t]?[e]?[r]?[i]?[t]?[y]?$/ ) return 'Dexterity' elsif attr.to_s.downcase.match( /^co[n]?[s]?[t]?[i]?[t]?[u]?[t]?[i]?[o]?[n]?$/ ) return 'Constitution' elsif attr.to_s.downcase.match( /^i[n]?[t]?[e]?[l]?[l]?[i]?[g]?[e]?[n]?[c]?[e]?$/ ) return 'Intelligence' elsif attr.to_s.downcase.match( /^w[i]?[s]?[d]?[o]?[m]?$/ ) return 'Wisdom' elsif attr.to_s.downcase.match( /^ch[a]?[r]?[i]?[s]?[m]?[a]?$/ ) return 'Charisma' else puts "#{attr} is an invalid attribute value." exit(1) end end # remove stupid formatting and align - flog: 35.1 def expand_attribute_arg2(attr) if attr.to_s.downcase.match /^s[t]?[r]?[e]?[n]?[g]?[t]?[h]?$/ return 'Strength' elsif attr.to_s.downcase.match /^d[e]?[x]?[t]?[e]?[r]?[i]?[t]?[y]?$/ return 'Dexterity' elsif attr.to_s.downcase.match /^co[n]?[s]?[t]?[i]?[t]?[u]?[t]?[i]?[o]?[n]?$/ return 'Constitution' elsif attr.to_s.downcase.match /^i[n]?[t]?[e]?[l]?[l]?[i]?[g]?[e]?[n]?[c]?[e]?$/ return 'Intelligence' elsif attr.to_s.downcase.match /^w[i]?[s]?[d]?[o]?[m]?$/ return 'Wisdom' elsif attr.to_s.downcase.match /^ch[a]?[r]?[i]?[s]?[m]?[a]?$/ return 'Charisma' else puts "#{attr} is an invalid attribute value." exit 1 end end # remove unnecessary to_s.downcase.match - flog: 9.7 def expand_attribute_arg3 attr if attr =~ /^s[t]?[r]?[e]?[n]?[g]?[t]?[h]?$/i return 'Strength' elsif attr =~ /^d[e]?[x]?[t]?[e]?[r]?[i]?[t]?[y]?$/i return 'Dexterity' elsif attr =~ /^co[n]?[s]?[t]?[i]?[t]?[u]?[t]?[i]?[o]?[n]?$/i return 'Constitution' elsif attr =~ /^i[n]?[t]?[e]?[l]?[l]?[i]?[g]?[e]?[n]?[c]?[e]?$/i return 'Intelligence' elsif attr =~ /^w[i]?[s]?[d]?[o]?[m]?$/i return 'Wisdom' elsif attr =~ /^ch[a]?[r]?[i]?[s]?[m]?[a]?$/i return 'Charisma' else puts "#{attr} is an invalid attribute value." exit 1 end end # remove unnecessary regexp [c][a][s][e][s] - flog: 9.7 def expand_attribute_arg4 attr if attr =~ /^st?r?e?n?g?t?h?$/i return 'Strength' elsif attr =~ /^de?x?t?e?r?i?t?y?$/i return 'Dexterity' elsif attr =~ /^con?s?t?i?t?u?t?i?o?n?$/i return 'Constitution' elsif attr =~ /^in?t?e?l?l?i?g?e?n?c?e?$/i return 'Intelligence' elsif attr =~ /^wi?s?d?o?m?$/i return 'Wisdom' elsif attr =~ /^cha?r?i?s?m?a?$/i return 'Charisma' else puts "#{attr} is an invalid attribute value." exit 1 end end # switch to case - flog: 9.6 def expand_attribute_arg5 attr case attr when /^st?r?e?n?g?t?h?$/i return 'Strength' when /^de?x?t?e?r?i?t?y?$/i return 'Dexterity' when /^con?s?t?i?t?u?t?i?o?n?$/i return 'Constitution' when /^in?t?e?l?l?i?g?e?n?c?e?$/i return 'Intelligence' when /^wi?s?d?o?m?$/i return 'Wisdom' when /^cha?r?i?s?m?a?$/i return 'Charisma' else puts "#{attr} is an invalid attribute value." exit 1 end end # now that it is a lot less complex, you can see a lot more clearly # that the regexps involved match a lot more than intended. eg: stgth # either, you need s(?:t(?:r(?:e(?:n(?:g(?:t(?:h)?)?)?)?)?)?)? (ugh) # or you need an entirely different approach: - flog: 13.6 def expand_attribute_arg6 attr { "strength" => 1, "dexterity" => 1, "constitution" => 2, "intelligence" => 1, "wisdom" => 1, "charisma" => 2, }.each do |str, len| return str.capitalize if attr.size >= len and str.index(attr.downcase) == 0 end end # or: require "abbrev" attribs = %w(strength dexterity constitution intelligence wisdom charisma) ATTRIBS = Abbrev::abbrev attribs # use abbrev - flog: 2.6 def expand_attribute_arg7 attr ATTRIBS[attr.downcase] end P.S. _NEVER_ exit from a library method. Raise and exit above. Rescuable, testable, maintainable.