ruby - Scanning through a hash and return a value if true -


based on hash, want match if it's in string:

def conv   str = "i have one, 2 or maybe sixty"   hash = {:one => 1, :two => 2, :six => 6, :sixty => 60 }   str.match( regexp.union( hash.keys.to_s ) ) end  puts conv # => <blank> 

the above not work matches "one":

str.match( regexp.union( hash[0].to_s ) ) 

edited:

any idea how match "one", "two" , sixty in string exactly?

if string has "sixt" return "6" , should not happen based on @cary's answer.

you need convert each element of hash.keys string, rather converting array hash.keys string, , should use string#scan rather string#match. may need play around regex until returns everyhing want , nothing don't want.

let's first @ example:

str = "i have one, 2 or maybe sixty" hash = {:one => 1, :two => 2, :six => 6, :sixty => 60} 

we might consider constructing regex word breaks (\b) before , after each word wish match:

r0 = regexp.union(hash.keys.map { |k| /\b#{k.to_s}\b/ })   #=> /(?-mix:\bone\b)|(?-mix:\btwo\b)|(?-mix:\bsix\b)|(?-mix:\bsixty\b)/  str.scan(r0)   #=> ["one", "two", "sixty"] 

without word breaks, scan return ["one", "two", "six"], "sixty" in str match "six". (word breaks zero-width. 1 before string requires string preceded non-word character or @ beginning of string. 1 after string requires string followed non-word character or @ end of string.)

depending on requirements, word breaks may not sufficient or suitable. suppose, example (with hash above):

str = "i have one, two, twenty-one or maybe sixty" 

and not wish match "twenty-one". however,

str.scan(r0)   #=> ["one", "two", "one", "sixty"]  

one option use regex demands matches preceded whitespace or @ beginning of string, , followed whitespace or @ end of string:

r1 = regexp.union(hash.keys.map { |k| /(?<=^|\s)#{k.to_s}(?=\s|$)/ }) str.scan(r1)   #=> ["sixty"]  

(?<=^|\s) positive lookbehind; (?=\s|$) positive lookahead.

well, avoided match of "twenty-one" (good), no longer matched "one" or "two" (bad) because of comma following each of words in string.

perhaps solution here first remove punctuation, allows apply either of above regexes:

str.tr('.,?!:;-','')   #=> "i have 1 2 twentyone or maybe sixty"   str.tr('.,?!:;-','').scan(r0)   #=> ["one", "two", "sixty"]   str.tr('.,?!:;-','').scan(r1)   #=> ["one", "two", "sixty"]  

you may want change / @ end of regex /i make match insensitive case.1

1 historical note readers want know why 'a' called lower case , 'a' called upper case.


Comments

Popular posts from this blog

node.js - Mongoose: Cast to ObjectId failed for value on newly created object after setting the value -

[C++][SFML 2.2] Strange Performance Issues - Moving Mouse Lowers CPU Usage -

ios - Possible to get UIButton sizeThatFits to work? -