[英]How do you effectively use regular expressions to find alliterative expressions?
我有一項作業要求我在 python 中使用正則表達式在包含名稱列表的文件中查找頭韻表達式。 下面是具體的說明:“ 打開一個文件並返回文件中的所有頭韻名稱。對於我們的目的,“名稱”是由空格分隔的兩個字母序列,只有大寫字母位於前導位置。我們稱之為如果名字和姓氏以相同的字母開頭,則是一個名稱頭韻,但 s 和 sh 被認為是不同的,對於 c/ch 和 t/th 也是如此。名稱文件將包含一個由逗號分隔的字符串列表。建議:分兩個階段進行。” 到目前為止,這是我的嘗試:
def check(regex, string, flags=0):
return not (re.match("(?:" + regex + r")\Z", string, flags=flags)) is None
def alliterative(names_file):
f = open(names_file)
string = f.read()
lst = string.split(',')
lst2 = []
for i in lst:
x=lst[i]
if re.search(r'[A-Z][a-z]* [A-Z][a-z]*', x):
k=x.split(' ')
if check('{}'.format(k[0][0]), k[1]):
if not check('[cst]', k[0][0]):
lst2.append(x)
elif len(k[0])==1:
if len(k[1])==1:
lst2.append(x)
elif not check('h',k[1][1]):
lst2.append(x)
elif len(k[1])==1:
if not check('h',k[0][1]):
lst2.append(x)
return lst2
我有兩個問題:首先,我編碼的內容對我來說似乎有意義,其背后的一般想法是我首先檢查名稱的格式是否正確(名字,姓氏,僅所有字母,僅名字和姓氏的第一個字母大寫),然后檢查名字和姓氏的起始字母是否匹配,然后查看這些第一個字母是否不是 cs 或 t,如果不是,我們將名稱添加到新的列表,如果它們是,我們檢查我們是否不小心將 [cst] 與 [cst]h 匹配。 代碼可以編譯,但是當我嘗試在以下姓名列表上運行它時:Umesh Vazirani、Vijay Vazirani、Barbara Liskov、Leslie Lamport、Scott Shenker、R2D2 Rover、Shaq、Sam Spade、Thomas Thing
它返回一個空列表,而不是它應該返回的 ["Vijay Vazirani", "Leslie Lamport", "Sam Spade", "Thomas Thing"]。 我在頭韻中添加了打印語句,所以看看哪里出了問題,似乎 if check('{}'.format(k[0][0]), k[1]): 是一個問題。
不僅僅是我的程序的問題,我覺得我錯過了正則表達式的重點:我是否過於復雜了? 有沒有更好的方法用正則表達式來做到這一點?
請考慮改進您的問題。
特別是這個問題只對那些想要回答完全相同問題的人有用,我認為這幾乎沒有機會。 請考慮如何改進,以便將其推廣到此 QA 可以對其他人有所幫助的程度。
我認為你的方向是正確的。
r'[AZ][az]* [AZ][az]*'
是一個很好的表達方式。re.match
和re.search
之間的區別。 re.search(r'[AZ][az]* [AZ][az]*', 'aaRob Smith')
返回一個 MatchObject。 看到這個。還評論一般的編程風格
first
和last
的可讀性,而不是k[0]
和k[1]
又是怎樣信k
挑!?)這是一種方法:
import re
FULL_NAME_RE = re.compile(r'^([A-Z][a-z]*) ([A-Z][a-z]*)$')
def is_alliterative(name):
"""Returns True if it matches the alliterative requirement otherwise False"""
# If not matches the name requirement, reject
match = FULL_NAME_RE.match(name)
if not match:
return False
first, last = match.group(1, 2)
first, last = first.lower(), last.lower() # easy to assume all lower-cases
if first[0] != last[0]:
return False
if first[0] in 'cst': # Check sh/ch/th
# Do special check
return _is_cst_h(first) == _is_cst_h(last)
# All check passed!
return True
def _is_cst_h(text):
"""Returns true if text is one of 'ch', 'sh', or 'th'."""
# Bad (?) assumption that the first letter is c, s, or t
return text[1:].startswith('h')
names = [
'Umesh Vazirani', 'Vijay Vazirani' , 'Barbara Liskov',
'Leslie Lamport', 'Scott Shenker', 'R2D2 Rover', 'Shaq' , 'Sam Spade', 'Thomas Thing'
]
print [name for name in names if is_alliterative(name)]
# Ans
print ['Vijay Vazirani', 'Leslie Lamport', 'Sam Spade', 'Thomas Thing']
試試這個正則表達式:
[a[0] for a in re.findall('((?P<caps>[A-Z])[a-z]*\\s(?P=caps)[a-z]*)', names)]
注意:它不處理 sh/ch/th 特殊情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.