Нужно понять, почему моя функция Python не выполняет надлежащее сравнение строк

1

Я заканчиваю онлайн-курс, который использует Python 3, и ниже я получаю подсказку:

Напишите функцию с именем is_valid. is_valid должен принимать два параметра: строку для проверки и строку всех допустимых символов.

is_valid должен возвращать логическое значение True, если все символы в проверяемой строке присутствуют в строке допустимых символов. Он должен возвращать False, если какой-либо символ в проверенной строке не появляется.

Я определил функцию, которая принимает два параметра, упомянутых в задаче, строку (которую в моем коде я называю строкой)) и строку допустимых символов (которую я назвал validcharacters).

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

def is_valid(string, validcharacters):
    for character in string:
        if character in validcharacters:
            return True
        else:
            return False

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

sample_valid_string = "1234-5678-9011-1111"
sample_invalid_string = "1234!5678.9011?1111"
valid_characters = "0123456789-"

print(is_valid(sample_valid_string, valid_characters))
print(is_valid(sample_invalid_string, valid_characters))

Я ожидаю, что выходные данные (для тестовых случаев, которые я перечислил выше) будут True и False соответственно. Однако, как написан мой код, он возвращает True и True. Я обнаружил, что при отладке он проходит только по первому символу моего кода и не может повторять другие символы. Я не уверен, как мне нужно переписать свой код, чтобы он проходил через другие символы перед возвратом True или False. Нужно ли мне переставлять свои декларации? Они заставляют функцию заканчиваться слишком рано?

Теги:
string
for-loop
function
return

5 ответов

1
Лучший ответ

Учитывая то, как вы определили is_valid, вы напрямую возвращаете True если первый символ в string находится в valid_characters. Вы должны возвращать True только после того, как проверили, что все символы действительны. Вместо этого вы должны делать что-то вроде:

def is_valid(string, validcharacters):
    for character in string:
        if character not in validcharacters:
            return False
    return True

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

def is_valid(string, validcharacters):
    return all(i in valid_characters for i in string)

Где all вернет True когда все элементы в выражении генератора также True.


Возвращаясь в этом случае:

print(is_valid(sample_valid_string, valid_characters))
print(is_valid(sample_invalid_string, valid_characters))

True
False
  • 1
    Вау, ваше объяснение имеет смысл, и это такое простое и элегантное решение, спасибо!
0

return сразу же выходит из функции, поэтому, если ваш цикл структурирован, он запускается только один раз.

Реорганизовать ваш цикл так, чтобы он возвращал False, если он находит недопустимый символ, и ожидает возврата True только тогда, когда он проходит через всю строку, не находя никаких недопустимых символов:

def is_valid(string, validcharacters):
    for character in string:
        if character not in validcharacters:
            return False
    return True
  • 0
    Спасибо за объяснение и за элегантный код, который вы написали! Имеет смысл для меня!
0
def is_valid(string, validcharacters):
    #Use a variable to track unmatched characters
    flag = True 
    for character in string:
        #If you find a unmatched char, set var to flag to False and break
        if character not in validcharacters: 
            flag = False 
            break
    return flag
  • 0
    Спасибо за предложение использовать перерыв, я бы не подумал об этом подходе!
0

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

def is_valid(string, validcharacters):
    # every character has to be in valid_characters for this to return 'True', 
    # otherwise it returns 'False'
    return all(character in valid_characters for character in string)
  • 0
    Спасибо за упоминание всей функции, я еще не сталкивался с этим, и это приятно знать!
0

Ваша функция возвращается слишком рано.

Прямо сейчас он видит, что первый символ, 1, находится в ваших допустимых символах, и возвращает true. Вам нужно убедиться, что вся строка верна. Отложите ваш return True пока не дойдете до конца цикла.

def is_valid(string, validcharacters):
    for character in string:
        if character in validcharacters:
            continue
        else:
            return False
    return True

Примечание: у него довольно большой большой O (https://en.wikipedia.org/wiki/Big_O_notation) из O (N ^ 2), поскольку он перебирает каждый символ в действительных символах, чтобы найти совпадение. Если вы хотите улучшить его, вы можете рассмотреть приведение списка действительных символов в виде набора (https://docs.python.org/3.7/library/stdtypes.html#set-types-set-frozenset) символов. Поиск соответствия в наборе O (1) по сравнению со списком O (n).

  • 0
    Спасибо за объяснение! Это имеет смысл для меня, и мне нравится использование продолжения, о котором я бы даже не подумал. Также спасибо за упоминание обозначения Big O Я еще не там, но хорошо бы подумать о том, как улучшить мою функцию.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню