使用正则表达式从字符串中提取去除的(1个元音,1个辅音)单词
注意:我正在学习正则表达式(regex),虽然我知道在这种情况下正则表达式不是最好的解决方案,但我还是想了解一下它是否可行。
任务:
你会得到一段包含不同单词的文本。这些单词之间用空格和标点符号分开。在这个任务中,数字不算作单词(字母和数字混合的也不算)。你需要计算那些元音和辅音交替出现的单词数量,也就是说,你计算的单词不能有两个连续的元音或辅音。由单个字母组成的单词不算在内——不要计算这些。字母的大小写在这个任务中不重要。
输入:一段文本,作为字符串(unicode格式)
输出:交替单词的数量,作为一个整数。
例如:
string1 = "Dog,cat,mouse,bird.Human." 应该返回 3。
1 个回答
2
我觉得有两种主要的方法来实现这个目标,首先要检查元音和辅音是否交替出现。
比如说,要检查字母 a
和 b
是否交替出现,你可以用这样的方式:
a(?:ba)+|b(?:ab)+
如果把这个方法扩展到元音和辅音,你就会得到一个比较长的正则表达式:
(?<![a-z])(?:[aeiou](?:[^P{L}aeiou][aeiou])+|[^\P{L}aeiou](?:[aeiou][^\P{L}aeiou])+)(?![a-z])
这里有两个负向前瞻 (?<![a-z])
和 (?![a-z])
,它们的作用是作为单词的边界,确保整个单词都被检查。
[aeiou]
是用来表示元音的,而 [^P{L}aeiou]
是用来表示辅音的。它相当于 [b-df-hj-np-tv-z]
。
第二种方法是确保单词中没有连续的元音或辅音。这种方法需要另一个负向前瞻,但相对较短:
(?<![a-z])(?:(?![aeiou]{2}|[^\P{L}aeiou]{2})[a-z])+(?![a-z])
你可以使用 re.findall
并激活 re.I
(或者在正则表达式开头使用 (?i)
)来获取所有匹配的结果,然后计算列表的长度来得到“条纹单词”的数量。
(?<![a-z]) # Ensure no letter before
(?:
(?!
[aeiou]{2} # Ensure no two consecutive vowel
|
[^\P{L}aeiou]{2} # Ensure no two consecutive consonant
)
[a-z] # Any letter
)+
(?![a-z]) # Ensure no more letters