Упрощение многих операторов if - PullRequest
0 голосов
/ 07 марта 2019

Есть ли способ упростить эту кучу операторов if?Эта функция синтаксического анализа, безусловно, работает (с правильными словарями), но она должна проверить 6 операторов if для каждого слова во входных данных.Для предложения из 5 слов это будет 30 операторов if.Его также трудно читать.

def parse(text):
    predicate=False
    directObjectAdjective=False
    directObject=False
    preposition=False
    indirectObjectAdjective=False
    indirectObject=False
    text=text.casefold()
    text=text.split()
    for word in text:
        if not predicate:
            if word in predicateDict:
                predicate=predicateDict[word]
                continue
        if not directObjectAdjective:
            if word in adjectiveDict:
                directObjectAdjective=adjectiveDict[word]
                continue
        if not directObject:
            if word in objectDict:
                directObject=objectDict[word]
                continue
        if not preposition:
            if word in prepositionDict:
                preposition=prepositionDict[word]
                continue
        if not indirectObjectAdjective:
            if word in adjectiveDict:
                indirectObjectAdjective=adjectiveDict[word]
                continue
        if not indirectObject:
            if word in objectDict:
                indirectObject=objectDict[word]
                continue
    if not directObject and directObjectAdjective:
        directObject=directObjectAdjective
        directObjectAdjective=False
    if not indirectObject and indirectObjectAdjective:
        indirectObject=indirectObjectAdjective
        indirectObjectAdjective=False
    return [predicate,directObjectAdjective,directObject,preposition,indirectObjectAdjective,indirectObject]

Вот также пример словаря, если это необходимо.

predicateDict={
"grab":"take",
"pick":"take",
"collect":"take",
"acquire":"take",
"snag":"take",
"gather":"take",
"attain":"take",
"capture":"take",
"take":"take"}

Ответы [ 4 ]

2 голосов
/ 07 марта 2019

Это больше вопрос проверки кода, чем вопрос переполнения стека. Основная проблема заключается в том, что у вас есть похожие данные, которые вы храните в отдельных переменных. Если вы объединяете свои переменные, вы можете перебирать их.

missing_parts_of_speech = ["predicate", [...]]
dict_look_up = {"predicate":predicateDict,
           [...]           
        }    
found_parts_of_speech = {}    
for word in text:
    for part in missing_parts_of_speech:
        if word in dict_look_up[part]:
            found_parts_of_speech[part] = dict_look_up[part][word]
            missing_parts_of_speech.remove(part)
            continue
1 голос
/ 07 марта 2019

Вы можете сопоставить слова различного типа (как строки) со словарями, где найти эти слова, а затем просто проверить, какие из них еще не были найдены, и найти их, если они в этих словах.

needed = {"predicate": predicateDict,
          "directObjectAdjective": adjectiveDict,
          "directObject": objectDict,
          "preposition": prepositionDict,
          "indirectObjectAdjective": adjectiveDict,
          "indirectObject": objectDict}

for word in text:
    for kind in needed:
        if isinstance(needed[kind], dict) and word in needed[kind]:
            needed[kind] = needed[kind][word]
            continue

В конце (и на каждом шаге в пути) все элементы в needed, которые не имеют dict в качестве значения, были найдены и заменены значением из их соответствующих dict.

(В ретроспективе, может быть более целесообразно использовать два словаря или один словарь и набор: один для окончательного значения для такого рода слов и один для того, были ли они уже найдены. Вероятно, будет немного легче понять.)

1 голос
/ 07 марта 2019

Я бы предложил просто использовать метод dict.get.Этот метод имеет необязательный аргумент default.Передав этот аргумент, вы можете избежать KeyError.Если ключ отсутствует в словаре, будет возвращено значение по умолчанию.

Если вы по умолчанию используете ранее назначенную переменную, она не будет заменена произвольным значением, а будет правильным значением.Например, если текущее слово является «предикатом», «прямой объект» будет заменен значением, уже сохраненным в переменной.


CODE

def parse(text):
    predicate = False
    directObjectAdjective = False
    directObject = False
    preposition = False
    indirectObjectAdjective = False
    indirectObject = False

    text=text.casefold()
    text=text.split()
    for word in text:
        predicate = predicateDict.get(word, predicate)
        directObjectAdjective = adjectiveDict.get(word, directObjectAdjective)
        directObject = objectDict.get(word, directObject)
        preposition = prepositionDict.get(word, preposition)
        indirectObjectAdjective = adjectiveDict.get(word, indirectObjectAdjective)
        indirectObject = objectDict.get(word, indirectObject)

    if not directObject and directObjectAdjective:
        directObject = directObjectAdjective
        directObjectAdjective = False

    if not indirectObject and indirectObjectAdjective:
        indirectObject = indirectObjectAdjective
        indirectObjectAdjective = False

    return [predicate, directObjectAdjective, directObject, preposition, indirectObjectAdjective, indirectObject]

PS: Используйте немного больше пробелов.Читатели будут вам благодарны ...


PPS: Я не проверял это, потому что у меня нет таких словарей под рукой.


PPPS: Это будетвсегда возвращайте last вхождений типов в тексте, в то время как ваша реализация всегда возвращает first вхождений.

0 голосов
/ 07 марта 2019

Я предлагаю вам использовать новый шаблон для написания этого кода вместо старого. Новый шаблон имеет 9 строк и остается 9 строк - просто добавьте больше словарей в D. Старый шаблон уже имеет 11 строк и будет расти по 4 строки с каждым дополнительным словарем для тестирования.

aDict = { "a1" : "aa1", "a2" : "aa1" }
bDict = { "b1" : "bb1", "b2" : "bb2" }
text = ["a1", "b2", "a2", "b1"]
# old pattern
a = False
b = False
for word in text:
    if not a:
        if word in aDict:
            a = aDict[word]
            continue
    if not b:
        if word in bDict:
            b = bDict[word]
            continue
print(a, b)
# new pattern
D = [ aDict, bDict]
A = [ False for _ in D]
for word in text:
    for i, a in enumerate(A):
        if not a:
            if word in D[i]:
                A[i] = D[i][word]
                continue
print(A)
...