2014-11-25 4 views
0

Я пытаюсь сделать метод, который может проверить, соответствует ли данная фраза хотя бы одному элементу из списка фраз и возвращает их. Ввод - это фраза, список фраз и словарь списков синонимов. Дело в том, чтобы сделать его универсальным.Верните список совпадений данной фразой

Вот пример:

phrase = 'This is a little house' 
dictSyns = {'little':['small','tiny','little'], 
      'house':['cottage','house']} 
listPhrases = ['This is a tiny house','This is a small cottage','This is a small building','I need advice'] 

Я могу создать код, который может сделать это на данном примере, который возвращает BOOL:

if any('This'+' '+'is'+' '+'a'+x+' '+y == phrase for x in dictSyns['little'] for y in dictSyns['house']): 
    print 'match' 

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

Можете ли вы дать мне совет, как это сделать, поэтому метод возвращает ['This is a tiny house','This is a small cottage'] в этом случае?

Выходной сигнал будет, как:

>>> getMatches(phrase, dictSyns, listPhrases) 
['This is a tiny house','This is a small cottage'] 

ответ

1

Я хотел бы подойти к этому следующим образом:

import itertools 

def new_phrases(phrase, syns): 
    """Generate new phrases from a base phrase and synonyms.""" 
    words = [syns.get(word, [word]) for word in phrase.split(' ')] 
    for t in itertools.product(*words): 
     yield ' '.join(t) 

def get_matches(phrase, syns, phrases): 
    """Generate acceptable new phrases based on a whitelist.""" 
    phrases = set(phrases) 
    for new_phrase in new_phrases(phrase, syns): 
     if new_phrase in phrases: 
      yield new_phrase 

Корень кода является назначение words, в new_phrases, который превращает phrase и syns в более полезную форму, список, в котором каждый элемент является списком приемлемых вариантов для этого слова:

>>> [syns.get(word, [word]) for word in phrase.split(' ')] 
[['This'], ['is'], ['a'], ['small', 'tiny', 'little'], ['cottage', 'house']] 

Обратите внимание на следующее:

  • Использование генераторов для более эффективной борьбы с большим количеством комбинаций (не строит весь список сразу);
  • Использование set для эффективного (O(1), vs. O(n) для списка) тестирование членства;
  • Использование itertools.product для генерации возможных комбинаций phrase на основе syns (вы также можете использовать itertools.ifilter при реализации); и
  • Style guide соответствие.

При использовании:

>>> list(get_matches(phrase, syns, phrases)) 
['This is a small cottage', 'This is a tiny house'] 

вещи думать о:

  • Что о случае символов (например, как следует "House of Commons" лечиться)?
  • Как насчет пунктуации?
+0

Спасибо, это очень помогло. Очень хороший подход. Случаи: Я бы изменил эту строку: if new_phrase.lowercase() в [x.lowercase() для x в фразах] .. Пунктуация (кома и точка): я бы использовал .strip (',') .strip ('. ') –

+1

@Milan обратите внимание, что ваш подход к нижнему регистру чрезвычайно неэффективен, так как он перерабатывает 'фразы' для каждой' new_phrase', не использует 'set' и не включает строчные буквы при генерации новых фраз. Вам также нужно будет тщательно подумать о том, на каком этапе «strip» (обратите внимание, что вы можете просто «strip» («,.»)). – jonrsharpe

0

я пошел об этом так:

for value in dictSyns: 
    phrase = phrase + dictSyns[value] 

for each_phrase in listPhrases: 
    if any(word not in phrase for word in each_phrase.split()): 
     pass 
    else: 
     print each_phrase 

Вероятно, не очень эффективно. Он создает список допустимых слов. Затем он сравнивает каждое слово в каждой строке с этим списком, и если нет неприемлемых слов, он печатает эту фразу.

EDIT: Я также понял, что это не проверяет грамматический смысл. Например, фраза «немного мало это а» все равно вернется как правильная. Это просто проверка каждого слова. Я оставлю это здесь, чтобы проявить свой позор.

Смежные вопросы