Поиск слова

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

charsInRow = input("Amount of characters in each row:n")
charsInCol = input("Amount of characters in each column:n")
allChar = input("Paste all the characters in:n")


def Main():
    PopulateArray()
    FindWords()


def PopulateArray():
    global allChar
    allChar.lower()
    allChar = list("".join(allChar.split()))
    return allChar


def IsValid():
    global charsInRow
    global charsInCol
    try:
        charsInRow = int(charsInRow)
        charsInCol = int(charsInCol)
    except ValueError:
        return False
    return True


def FindWords():
    wordToFind = input("What word would you like to search?")
    wordToFind.lower()
    wordSearched = ""
    x = 0
    for n in range(0, len(allChar) - 1):
        if allChar[n] == wordToFind[0]:
            while x <= len(wordToFind):
                for i in range(0, len(wordToFind) * charsInRow, charsInRow):
                    try:
                        if allChar[n + i] == wordToFind[x]:
                            wordSearched = wordSearched + allChar[n + i]
                            n = n + i
                            break
                    except IndexError:
                        pass

                    try:
                        if allChar[n - i] == wordToFind[x]:
                            wordSearched = wordSearched + allChar[n-i]
                            n = n-i
                            break
                    except IndexError:
                        pass

                    try:
                        if allChar[(n + i) + 1] == wordToFind[x]:
                            wordSearched = wordSearched + allChar[(n+i) + 1]
                            n = (n+i) + 1
                            break
                    except IndexError:
                        pass

                    try:
                        if allChar[(n - i) + 1] == wordToFind[x]:
                            wordSearched = wordSearched + allChar[(n - i) + 1]
                            n = (n - i) + 1
                            break
                    except IndexError:
                        pass

                    try:
                        if allChar[(n - i) - 1] == wordToFind[x]:
                            wordSearched = wordSearched + allChar[(n - i) - 1]
                            n = (n - i) - 1
                            break
                    except IndexError:
                        pass

                    try:
                        if allChar[(n + i) - 1] == wordToFind[x]:
                            wordSearched = wordSearched + allChar[(n + i) - 1]
                            n = (n + i) - 1
                            break
                    except IndexError:
                        pass

                    try:
                        if allChar[(n + 1)] == wordToFind[x]:
                            wordSearched = wordSearched + allChar[n + 1]
                            n = n + 1
                            break
                    except IndexError:
                        pass

                    try:
                        if allChar[(n - 1)] == wordToFind[x]:
                            wordSearched = wordSearched + allChar[n - 1]
                            n = n - 1
                            break
                    except IndexError:
                        pass
                x += 1

    if wordToFind == wordSearched:
        print(True)
    else:
        print(False)

    print(wordSearched)


if IsValid():
        if len(allChar) == int(charsInRow) * int(charsInCol):
            Main()
        else:
            print("Not correct amount of characters, please try again")
else:
    print("Please input numerical values for amount of characters.")
input()

2 ответа
2

Именование

Чтобы ваши имена были сложными для PEP8, как имена ваших методов, так и имена переменных должны принимать lower_snake_case, т.е.

chars_in_row
all_char
populate_array
find_words

Побочные эффекты

IsValid обеспокоен. Оно делает нет делайте то, что написано на банке, — он не только проверяет достоверность двух переменных, но и преобразует их на месте. Кроме того, он неправильно использует глобальные переменные.

Лучшее название для этого было бы try_parse, возможно, принимая одну строку, не затрагивая глобальные объекты и возвращая Optional[int] то есть None если недействительно.

Повторные попытки

Для ваших блоков, которые выглядят так:

                try:
                    if allChar[n + i] == wordToFind[x]:
                        wordSearched = wordSearched + allChar[n + i]
                        n = n + i
                        break
                except IndexError:
                    pass

есть две основные проблемы. Во-первых, вы должны просмотреть список индексов, начиная с n + i, n - iи т.д., чтобы вам не приходилось повторять эти блоки; Например

indices = (
    n + i,
    n - i,
    # ...
)
for index in indices:
    # ...

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

  • Не совсем уверен, что подразумевается под циклическим просмотром списка индексов, как это будет выглядеть?

    — madine816

  • Отредактировано; показан кортеж вместо списка, но та же идея

    — Райндериен

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

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

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

import argparse
import sys

def main(args):
    # Get user arguments.
    opts = parse_args(args)

    # Validate user inputs.
    ...

    # Compute any need information, such as the number
    # of columns and other data you might want to assist with
    # searching (more on that below).
    cols = len(opts.characters) // opts.rows

    # Perform the word search.
    searches = find_words(opts.characters, opts.rows, opts.cols, opts.words)

    # Report to user. Enhance as needed.
    print(searches)

def parse_args(args):
    ap = argparse.ArgumentParser()
    ap.add_argument('characters')
    ap.add_argument('words', nargs="*")
    ap.add_argument('--rows', type = int)
    return ap.parse_args(args)

def find_words(characters, rows, cols, words):
    # Do the searching, collecting results in some type
    # of data structure or object.
    searches = {
        w : w in characters
        for w in words
    }

    # Return that information to main().
    # Do not print() here. Keep algorithm and presentation separate.
    return searches

if __name__ == '__main__':
    main(sys.argv[1:])

Как вы отметили, ваш текущий подход к поиску очень сложен и требует повторения. Из-за этого он подвержен ошибкам, его трудно рассуждать, и неудобно менять в будущем. У него также есть некоторые ошибки: например, при моей попытке использования ему не удалось найти слова на обратной диагонали. Нет особого смысла просматривать код в его текущем состоянии. Вам нужен лучший план.

Есть много способов упростить ситуацию. Одно из предложений — перестать писать логику поиска слов и вместо этого рассмотреть этот вопрос. Как можно реорганизовать данные, чтобы упростить поиск слов? Вот одна идея:

# Given this:
characters="catsdogseels"

# Create this:
grid = [
    # The rows.
    'cats',
    'dogs',
    'eels',
    'cde',
    # The columns.
    'aoe',
    'tgl',
    'sss',
    # The diagonals.
    'c',
    'da',
    'eot',
    'egs',
    'ls',
    's',
],

Строки легко создавать, используя способность Python разбивать списки различными способами. Столбцы могут быть созданы путем транспонирования строк. Вы можете поискать в Интернете, как написать transpose() функции в нескольких строках кода.

Диагонали хитрее, но вот один способ:

# Start with the rows.
'cats'
'dogs'
'eels'

# Shift and pad them.
'cats  '
' dogs '
'  eels'

# Then transpose() those values and strip off the spaces.

  • одного измерения будет достаточно. — OP заявляет, что вход может быть квадратным или прямоугольным, поэтому, если вы сделаете вывод об одном измерении, вы не сможете подтвердить, что вход имеет правильную длину для второго. Может быть, это и нормально, но стоит отметить.

    — Райндериен

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

    — Райндериен

  • Под «неспособным оправдать» я имею в виду «трудно оправдать» — мои грамматические железы явно еще не проснулись.

    — Райндериен

  • @Reinderien Возможно, я неправильно понял, что делает OP, или что-то упустил, но если вы скажете мне, что есть 5 строк и дадите мне 20 символов, 4 столбца покажутся безопасным выводом. И ваш input() По моему опыту, примеры в основном являются крайними случаями. Подавляющему большинству программ командной строки это не нужно. Рассмотрим набор инструментов Unix: интерактивность пользователя составляет крошечную долю от всех видов использования. Я стону каждый раз, когда вижу учебные материалы по Python, побуждающие новых программистов писать так много программ CLI, которые вращаются вокруг утомительной интерактивности в стиле вопросов и ответов. Это заблуждение и учит вредным привычкам.

    — FMc

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *