Из набора слов, вывести все слова, которые соответствуют строки случайных букв (как Эрудит)


Я в мой первый год программирования С Python 3, и я интересно, если кто имеет лучший способ, чтобы запрограммировать эту проблему. Когда пользователь обеспечивает до 7 случайных букв в одной строке, программа должна прочитать файл wordlist.txt ‘список слов из файла, которые могут быть построены, используя некоторые или все из этих писем.

Например, если пользователь предоставляет трех букв, ‘аэр’ как строку, программа будет предлагать следующие слова из данного файла: 'АЕ', 'АР', 'ЕСТЬ', 'ЭКСПЕРТ', 'УХО', 'Э', 'ЭРА', 'РЕ'

Это что у меня есть сейчас:

wordlist=list(line.strip('\n') for line in open('wordlist.txt','r'))

def wordFinder():
    words=[]
    letters=str.upper(input('enter up to 7 letters:'))
    for word in wordlist:
        candidate=True
        letterlist=list(letters)
        for letter in word:
            if letter not in letterlist:
                candidate=False
                break
            else:
                letterlist.remove(letter)
        if candidate==True:
            words.append(word)                
    return words

>>>options()

enter up to 7 letters:aer
>>>['AE', 'AR', 'ARE', 'EA', 'EAR', 'ER', 'ERA', 'RE']

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

def options2():
    words=[]
    letters=set(str.upper(input('Enter up to 7 letters:')))
    words=[w for w in wordlist
        if set(w).issubset(letters)
        and len(w)<=len(letters)]
    return words

>>>options2()

enter up to 7 letters:aer
>>>['AA','AE','AR','ARE','EA','EAR','EE','ER','ERA','ERE','ERR','RE','REE']

Если любые изменения могут быть сделаны для второй функции для работы это было бы здорово.



2101
4
задан 29 марта 2018 в 01:03 Источник Поделиться
Комментарии
2 ответа

Способ обработки файла не является идеальным. Это не очевидно в такой маленькой программе, но вы не .close()-Инг файла после его открытия. Конечно, Python будет закрыть файл после того, как программа закончила свое выполнение, но в большей приложения, используя Ваш метод будет неуклюжим, поскольку вам придется забыть позвонить .close() каждый раз, когда вы открываете файл. В Python with сайта может позаботиться об этом для вас, хотя.

with open('wordlist.txt','r') as file:
wordlist=list(line.strip('\n') for line in file
# more file handling code...

# file will be automagically closed after `with` block exits


Я думаю, что ваш wordFinder функция делает слишком много (также в PEP8 конвенции , он должен быть назван word_finder). Я ожидаю, что функция с именем, как это просто найти и вернуть слова, но он также обрабатывает пользовательский ввод, который я думаю, должна быть отдельная функция.


Говоря о обработку входных данных, ваша программа, кажется, не ручка символы на всех. Что происходит, когда пользователь вводит abc_123 в качестве входных данных? Я предполагаю, что это будет просто использовать ABC_123 чтобы посмотреть на ваш файл, и возвращает результаты по ABC после того, как обнаруживает ничего для _123. Мое предложение было бы сделать вход в while цикл, и выход из цикла только после проверки:

input_is_only_letters = False
while not input_is_only_letters:
letters = str.upper(input('enter up to 7 letters:'))
if letters.isalpha():
input_is_only_letters = True
else:
print('Please enter only letters A-Z (not case sensitive)')

Я также хотел обернуть эту логику в свою собственную функцию, которая возвращает входной.


Несколько мелочей:


  • Поскольку вы используете Python 3, Вы можете (и Имо) использовать типа намекает, что я и сделал в приведенном ниже коде.

  • Получить в привычку делать отдельную функцию для каждого "действия" или отдельный вид вещь. Это делает отладку и тестирование кода гораздо проще.

  • Когда вы присваиваете значения, использовать пространство с каждой стороны от знака равенства, например, my_value = 42.

  • Использовать snake_case именование функций, переменных и т. д.

  • Вам не нужно проверять if my_var == True: или if my_var == False:вы можете просто написать if my_var: и if not my_var:

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

  • Возьмите в привычку выполнять свои автономные звонки в if __name__ == '__main__'так что если вы были, чтобы импортировать это в другом модуле, она не выполнит сам файл, когда оно заряжено. Смотрите эту статью на thepythonguru.com для получения дополнительной информации.

  • Я не посмотрел на ваш список осмысления кода, может еще кто-нибудь придумать способ, чтобы сделать это таким образом.


Мой рефакторинг кода.

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

from typing import List

def get_7_letters_input() -> str:
"""Captures up to 7 letters from stdin"""
input_is_only_letters = False
while not input_is_only_letters:
letters = str.upper(input('enter up to 7 letters:'))
if letters.isalpha():
if len(letters) <= 7:
input_is_only_letters = True
else:
print('Please enter no more than 7 letters')
else:
print('Please enter only letters A-Z (not case sensitive)')
return letters

def get_words_from_file(filename: str) -> List:
"""Opens a file and splits it into a list for each new line"""
with open(filename, 'r') as file:
return list(line.strip('\n') for line in file

def find_words_matching_letters(letters: str) -> List:
"""Find words that match the letters provided"""
words = []
word_list = get_words_from_file('wordlist.txt')

for word in word_list:
candidate = True
letterlist = list(letters)
for letter in word:
if letter not in letterlist:
candidate = False
break
else:
letterlist.remove(letter)
if candidate:
words.append(word)
return words

if __name__ == '__main__':
find_words_matching_letters(get_7_letters_input())

3
ответ дан 29 марта 2018 в 04:03 Источник Поделиться

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

candidate=True
letterlist=list(letters)
for letter in word:
if letter not in letterlist:
candidate=False
break
else:
letterlist.remove(letter)

Операции letter not in letterlist и letterlist.remove(letter) потребуется время, пропорциональное длине letterlistи это должно быть сделано для каждой буквы в word, делая во время выполнения для проверки пропорциональна произведению числа букв в два слова.

Можно выполнить эту проверку в линейное время путем подсчета числа вхождений каждой буквы в слове, например, с помощью collections.Counter. Во-первых, нужно подсчитать вхождений каждой буквы в ввода:

letter_counts = Counter(letters)

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

all(n <= letter_counts[c] for c, n in Counter(word).items())

2
ответ дан 29 марта 2018 в 10:03 Источник Поделиться