簡體   English   中英

Python-對於Itertools排列循環,如何不創建無盡的Elif陳述?

[英]Python - For Loop of Itertools Permutations, How to not Create Endless Elif Statments?

我是python /編程新手,已經使用了幾個月。 希望這段代碼對於SO來說不會太大或太高,但是我無法弄清楚在沒有完整上下文的情況下如何問這個問題。 因此,這里去:

import re
import itertools

nouns = ['bacon', 'cheese', 'eggs', 'milk', 'fish', 'houses', 'dog']
CC = ['and', 'or']

def replacer_factory():
    def create_permutations(match):
        group1_string = (match.group(1)[:-1]) # strips trailing whitespace
        # creates list of matched.group() with word 'and' or 'or' removed
        nouns2 = filter(None, re.split(r',\s*', group1_string)) + [match.group(3)] 
        perm_nouns2 = list(itertools.permutations(nouns2))
        CC_match = match.group(2) # this either matches word 'and' or 'or'

        # create list that holds the permutations created in for loop below
        perm_list = []
        for comb in itertools.permutations(nouns2):
            comb_len = len(comb)
            if comb_len == 2:
                perm_list.append(' '.join((comb[0], CC_match, comb[-1])))

            elif comb_len == 3:
                perm_list.append(', '.join((comb[0], comb[1], CC_match, comb[-1])))

            elif comb_len == 4:
                perm_list.append(', '.join((comb[0], comb[1], comb[2], CC_match, comb[-1])))

        # does the match.group contain word 'and' or 'or'
        if (match.group(2)) == "and":
            joined = '*'.join(perm_list)
            strip_comma = joined.replace("and,", "and")
            completed = '|'+strip_comma+'|'
            return completed

        elif (match.group(2)) == "or":
            joined = '*'.join(perm_list)
            strip_comma = joined.replace("or,", "or")
            completed = '|'+strip_comma+'|'
            return completed       

    return create_permutations

def search_and_replace(text):
    # use'nouns' and 'CC' lists to find a noun list phrase
    # e.g 'bacon, eggs, and milk' is 1 example of a match
    noun_patt = r'\b(?:' + '|'.join(nouns) + r')\b'
    CC_patt = r'\b(' + '|'.join(CC) + r')\b' 
    patt = r'((?:{0},? )+){1} ({0})'.format(noun_patt, CC_patt)

    replacer = replacer_factory()
    return re.sub(patt, replacer, text)

def main():
    with open('test_sentence.txt') as input_f:
        read_f = input_f.read()

    with open('output.txt', 'w') as output_f:
        output_f.write(search_and_replace(read_f))


if __name__ == '__main__':
    main()

“ test_sentence.txt”的內容:

I am 2 list with 'or': eggs or cheese.
I am 2 list with 'and': milk and eggs.
I am 3 list with 'or': cheese, bacon, and eggs.
I am 3 list with 'and': bacon, milk and cheese.
I am 4 list: milk, bacon, eggs, and cheese.
I am 5 list, I don't match.
I am 3 list with non match noun: cheese, bacon and pie.

因此,代碼都很好用,但是我遇到了一個局限性,我不知道該怎么解決。 此限制包含在for循環中。 就目前而言,我只創建了'if'和'elif'語句,它們僅達到elif comb == 4: 我實際上希望elif comb == 5:變得不受限制,然后轉到elif comb == 5:elif comb == 6:elif comb == 7: (嗯,在實際中,我真的不需要超越elif comb == 20 ,但是要點是一樣的,我想允許這種可能性)。 但是,創建這么多的“ elif”語句並不現實。

關於如何解決這個問題的任何想法?

請注意,此處的“ test_sentence.txt”和變量“ noun”的列表僅是示例。 我實際上的“名詞”列表在1000左右,我將使用“ test_sentence.txt”中包含的較大文檔。

干杯達倫

附言-我努力為這個找到合適的標題!

如果您注意到了, if-elif語句中的每一行都遵循大致相同的結構:首先獲取comb列表中除最后一個元素之外的所有元素,添加CC_match ,然后添加最后一項。

如果我們將其寫為代碼,則會得到如下內容:

head = list(comb[0:-1])
head.append(CC_match)
head.append(comb[-1])
perm_list.append(', '.join(head))

然后,在您的for循環內,您可以替換if-elif語句:

for comb in itertools.permutations(nouns2):
    head = list(comb[0:-1])
    head.append(CC_match)
    head.append(comb[-1])
    perm_list.append(', '.join(head))

您還應該考慮添加一些錯誤檢查,以使如果comb列表的長度等於零或一,程序不會產生奇怪的反應。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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