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
Post a Comment