Как ограничить результаты оператора Python if-in при проверке, найдена ли строка в другой строке? - PullRequest
0 голосов
/ 28 мая 2020

Я написал Python для l oop, который проходит через каждое слово на английском sh языке (из слов импорта nltk.corpus) и печатает слова, состоящие только из 6 букв, предоставленных пользователем. 6 пользовательских вводов хранятся в списке с именами символов, поэтому for l oop сравнивает элементы из списка с каждой строкой (engli sh слов).

Проблема в том, что слова печатаются, содержат несколько символов одного и того же символа. Например, если это символы 'u, l, c, i, e, n', будут возвращены слова из нескольких букв, такие как «сосулька». Как запретить скрипту возвращать слова с повторяющимися буквами?

characters = [input1, input2, input3, input4, input5, input6]

for word in word_list:
    word = word.lower()
    if len(word) == 3:
        if word[0] in characters and word[1] in characters and word[2] in characters:
            print(word)
    elif len(word) == 4:
        if word[0] in characters and word[1] in characters and word[2] in characters and word[3] in characters:
            print(word)
    elif len(word) == 5:
        if word[0] in characters and word[1] in characters and word[2] in characters and word[3] in characters and word[4] in characters:
            print(word)
    elif len(word) == 6:
        if word[0] in characters and word[1] in characters and word[2] in characters and word[3] in characters and word[4] in characters and word[5] in characters:
            print(word)

Я знаю, что код написан неэффективно, поэтому я также был бы признателен за советы по улучшению. Пример результатов вышеуказанного скрипта:

eel
eileen
eli
ell
elle
ellen
ellice
encell
ennui
eunice
ice
iceni
icicle
ilicic
ilicin
ill
inn
inulin

Ответы [ 5 ]

1 голос
/ 28 мая 2020

Я не знаю этот пакет, но похоже, что у вас большой список слов. Вам следует использовать дерево ключевых слов вместо того, чтобы каждый раз перебирать весь список при вводе новых букв. Возможно, этот пакет содержит лучшие структуры данных для доступа к этим словам, в противном случае вам следует преобразовать его в Tr ie. Это разовая задача, и после нее время поиска увеличивается для каждого ввода.

Отвечая на ваш вопрос, вы можете сделать словарь, который сопоставляет введенные буквы с их количеством . Например:

input = {'a':1, 'b':2, 'c':1}

Затем, если вы зацикливаете каждое слово, дорого вы можете пересчитать каждую букву. Если вы используете Tr ie, вам нужно только go для дочерних элементов и сделать рекурсивный вызов, если

input[children's letter] != 0

перед рекурсивным вызовом вам нужно уменьшить это значение, а после

Таким образом, вы только go перебираете слова, которые начинаются так же, как ваши буквы, вместо того, чтобы каждый раз переходить по каждому слову.

Надеюсь, это поможет :)

1 голос
/ 28 мая 2020

Это не проверено, поскольку у меня нет тестовых данных, но должно быть:

characters = [input1, input2, input3, input4, input5, input6]

for word in word_list:
    word = word.lower()
    isIn = True
    for c in word:
        if c not in characters or word.count(c) != 1:
            isIn = False
    if isIn:
        print(word)
0 голосов
/ 28 мая 2020

Вы можете использовать collections.Counter.

from collections import Counter

Затем, чтобы получить объекты Counter (по сути, мультимножества), которые подсчитывают, сколько раз каждый символ встречается в слове и во введенных разрешенных символах:

word_counter = Counter(word)
characters_counter = Counter(characters)

Чтобы проверить, что слово является подмножеством символов, и напечатать, если да, выполните

if word_counter & characters_counter == word_counter:
    print(word)

(& означает пересечение)

Очень просто. Быстро, потому что он использует стандартные библиотечные функции, такие как sh карты, которые оптимизированы и, вероятно, написаны на C, вместо дорогостоящих многоуровневых циклов списков, а также поиска, добавления и удаления. У него также есть дополнительное преимущество, заключающееся в том, что если пользователь вводит одни и те же символы несколько раз, то он позволяет слова с этим символом повторяться несколько раз, вплоть до того, сколько раз пользователь ввел его.

Например, если пользователь ввел «i, i, c, c, l, e», тогда слово «сосулька» все равно будет напечатано, тогда как если бы он ввел «i, i, c, z, l, e», тогда «сосулька» не будет напечатана.

from collections import Counter

# input characters, get words...

characters_counter = Counter(characters)
for word in word_list:
    word_counter = Counter(word)
    if word_counter & characters_counter == word_counter:
        print(word)

Готово!

0 голосов
/ 28 мая 2020

Не тестировал:

   for word in word_list:
        if word < 6:
            if all(letter in character for letter in list(word.lower()):
                print(word)
0 голосов
/ 28 мая 2020

Моя первая мысль об эффективности:

def test_word(word, characters):
    for i in range(len(word)):
        if word[i] not in characters:  # Does everything in 2 lines :)
            return False
    return True

Эта функция возвращает False, если слово имеет буквы, не входящие в список "characters", и True в противном случае. Я использовал функцию просто потому, что она более аккуратная и вы можете легко запустить код из любой точки программы. Убедитесь, что вы используете копию списка «символы», если вам нужно будет использовать его в будущем:

copy_of_chars = characters.copy()
test_word(word, copy_of_chars)

О повторяющихся буквах - я бы удалил любую букву в списке, которая была «найдена» :

def test_word(word, characters):
    for i in range(len(word)):
        if word[i] not in characters:
            return False
        characters.pop(characters.index([word[i]]))  # Removes the letter from the list "characters"
    return True

Эта функция вернет False, если в слове есть символы, которых нет в списке символов, или если в нем несколько букв, когда в списке «символы» можно найти только одну. В противном случае он вернет True.

Надеюсь, это поможет!

...