簡體   English   中英

您如何有效地使用正則表達式來查找頭韻表達式?

[英]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.matchre.search之間的區別。 re.search(r'[AZ][az]* [AZ][az]*', 'aaRob Smith')返回一個 MatchObject。 看到這個

還評論一般的編程風格

  • 更好的命名變量firstlast的可讀性,而不是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM