RGX = /
( # begin capture group 1
\b # match a word boundary
[a-z]+ # match one or more lowercase letters
\b # match a word boundary
) # end capture group 1
(?! # begin negative lookahead
.* # match zero or more characters
\b # match a word boundary
\1 # match the contents of capture group 1
\b # match a word boundary
) # end negative lookahead
/x # use free-spacing regex definition mode
def find_em(str)
str.downcase.scan(RGX).size
end
1条答案
按热度按时间agxfikkp1#
让我们考虑一下实现这一目标的各种方法。
让我们使用下面的字符串(查克·狄更斯写的一个相当长的句子的开头)。
请注意
/[a-z]+/
匹配一个或多个小写字母,尽可能多。见字符串#扫描和阵列#Uniq。
请注意,前面的方法生成一个中间数组
str.downcase.scan(/[a-z]+/)
。我们可以按如下方式避免这种情况。这使用了(很少使用的)形式的字符串#gSub,它接受一个参数,但不接受块,从而产生一个枚举数。它只枚举正则表达式
/[a-z]+/
的匹配项,因此与字符串替换无关。先前的方法有效,但具有对找到的每个单词
s
采用线性搜索(a.include?(s)
)的缺点。我们可以通过构造一个集合(根据定义,该集合具有唯一的元素)并在最后将其转换为数组来解决这个问题。请参见Set::New、Set#<<和Set#Include?
另一种变体是将
scan
与更复杂的正则表达式一起使用。我将以“自由空格模式”表达这个正则表达式,以使其自记录。请注意
此正则表达式是按常规编写的
或者,我们可以使用
gsub
的奇怪形式,它完全避免了数组的构造。请参见枚举器#count。