Ruby's "hello world".scan(/(\w){2}/) is not the same as "hello world".scan(/\w{2}/)?
I thought I knew scan
in Ruby: as if it is doing a single match, but repeat it for all results and put i开发者_开发技巧nto array?
ruby-1.9.2-p0 > "hello world".scan(/\w{2}/)
=> ["he", "ll", "wo", "rl"]
ruby-1.9.2-p0 > "hello world".scan(/(\w){2}/)
=> [["e"], ["l"], ["o"], ["l"]]
How come the second line resulted that -- and how do you make it return the same result as line 1? (because sometimes we have to add ()
to the regex.
as a contract, with or without ()
, the following are the same:
ruby-1.9.2-p0 > "hello world"[/\w{2}/]
=> "he"
ruby-1.9.2-p0 > "hello world"[/(\w){2}/]
=> "he"
The parens create a match group. Try /(?:\w){2}/
instead.
I found something more:
scan
seems to work using group if there is any, so that's why the behavior of the 2nd line was like that. (using the last matched content inside ( )
and use that in the results inside the array.)
As a test: (if there are multiple groups, then all groups go into one array)
ruby-1.9.2-p0 > "hello world".scan(/((\w){2})/)
=> [["he", "e"], ["ll", "l"], ["wo", "o"], ["rl", "l"]]
This is a way to get it: alway add top level ( )
, and use map
to get the first element in array (ie, the top level match):
ruby-1.9.2-p0 > "hello world".scan(/((\w){2})/).map {|e| e.first}
=> ["he", "ll", "wo", "rl"]
But I would still like to find simpler answer...
精彩评论