#python
#python
Вопрос:
Я хочу разрешить пользователю вводить строку, за которой следует целое число, разделенное запятой, и если они не соответствуют, я хотел бы сообщить им, что они ввели неверно, и позволить им повторить попытку. У меня возникли проблемы с поиском способа сделать это, я могу сделать так, чтобы для ввода требовалась запятая, но я не знаю, как указать string и int с каждой стороны.
name_age = []
user_input = []
name_age2 = []
ages = []
while user_input != "":
try:
user_input = input("Type 'Name,Age': ")
name_age.append(user_input)
print(name_age)
if "," not in user_input:
raise ValueError
except ValueError:
print("Incorrect try again")
else:
name_age.remove("")
for item in name_age:
name_age2.append(item.split(','))
for pair in name_age2:
for val in pair:
if val.isdigit():
ages.append(int(val))
print(name_age2)
print(ages)
print("Names amp; Ages: ", name_age2)
print("Total of ages: ", sum(ages))
print("Average of ages: ", sum(ages) / len(ages))
print("Total number of names: ", len(name_age2))
print("End")
Комментарии:
1. не могли бы вы привести пример допустимой строки?
2. @collinsuz ‘джон,24’
Ответ №1:
вы можете, например, создать функцию для проверки пользовательского ввода, например, так. Вот пример, он работает, но вам нужно внести некоторые изменения.
name_age = []
user_input = []
name_age2 = []
ages = []
def validate(input: str) -> bool:
decomposed_string: str = input.split(',')
if decomposed_string[1].isdigit() and not decomposed_string[0].isdigit():
return True
return False
while user_input != "":
try:
user_input = input("Type 'Name,Age': ")
name_age.append(user_input) if validate(user_input) else print("Incorrect, try again")
print(name_age)
if "," not in user_input:
raise ValueError
except ValueError:
print("Incorrect try again")
else:
name_age.remove("")
for item in name_age:
name_age2.append(item.split(','))
for pair in name_age2:
for val in pair:
if val.isdigit():
ages.append(int(val))
print(name_age2)
print(ages)
print("Names amp; Ages: ", name_age2)
print("Total of ages: ", sum(ages))
print("Average of ages: ", sum(ages) / len(ages))
print("Total number of names: ", len(name_age2))
print("End")
Комментарии:
1. Чувак, я пробовал anding ранее сегодня вечером и не смог этого сделать, увидев, что ваш пример очень помог, я вставил «если и нет» в свой код и смог удалить исключение, спасибо!
if decomposed_string[1].isdigit() and not decomposed_string[0].isdigit():
Ответ №2:
Шаблоны регулярных выражений очень хорошо подходят для такого простого синтаксического анализа строк. Другим решением в сложных случаях было бы обратиться к какой-либо сторонней библиотеке PyParsing или Parsley.
С регулярными выражениями группы и особенно именованные группы очень удобны. Вот простой пример:
name_age_pattern = re.compile(r'(?P<name>w ),(?P<age>d )')
def parse_name_age(string):
match = name_age_pattern.match(string)
if not match:
raise ValueError('input string didnt match pattern')
return match.group('name'), int(match.group('age'))
name, age = parse_name_age('Jack,23')
Затем несколько дополнительных подсказок. Чтобы сделать ваш код немного более питоническим, вы могли бы использовать некоторые классы. Вот пример:
import re
from typing import NamedTuple
class Person(NamedTuple):
name: str
age: int
name_age_pattern = re.compile(r'(?P<name>w ),(?P<age>d )')
@classmethod
def from_string(cls, string):
match = cls.name_age_pattern.match(string)
if not match:
raise ValueError('input string didnt match pattern')
return cls(match.group('name'), int(match.group('age')))
class People(list):
# Inheriting from a list should be made with caution. Overriding
# native functions could result unwanted side effects. We should
# be safe here since we don't do so.
@property
def names(self):
return ', '.join((person.name for person in self))
@property
def total_age(self):
return sum((person.age for person in self))
@property
def avg_age(self):
return self.total_age / len(self)
people = People()
while True:
input_str = input('Please give a name and age separated by a comma.')
if input_str == "":
break
try:
people.append(Person.from_string(input_str))
except ValueError as e:
print(e)
print(people.names)
print(f'sum of ages: {people.total_age}')
print(f'avg of ages: {people.avg_age}')
Комментарии:
1. Большое вам спасибо, я еще не добрался до регулярных выражений или классов, но как только я это сделаю, я обязательно вернусь к этому и попытаюсь переписать эту программу более эффективно, используя это для некоторой практики и обучения, спасибо за ваше время!
Ответ №3:
Здесь я использовал регулярное выражение для вашего условия для проверки ввода:
import re
name_age = []
user_input = []
name_age2 = []
ages = []
while user_input != "":
try:
user_input = input("Type 'Name,Age': ")
name_age.append(user_input)
print(name_age)
if not re.search('^w (s w )*,d ', user_input):
raise ValueError
except ValueError:
print("Incorrect try again")
else:
name_age.remove("")
for item in name_age:
name_age2.append(item.split(','))
for pair in name_age2:
for val in pair:
if val.isdigit():
ages.append(int(val))
print(name_age2)
print(ages)
print("Names amp; Ages: ", name_age2)
print("Total of ages: ", sum(ages))
print("Average of ages: ", sum(ages) / len(ages))
print("Total number of names: ", len(name_age2))
print("End")
Итак, это регулярное выражение будет принимать имена с пробелами, например «аноша рехан, 12», но если вы ищете имена только из одного слова, используйте это регулярное выражение '(w )*,d '
Ответ №4:
Вы можете использовать регулярное выражение, чтобы соответствовать точному шаблону, который вы хотите от ввода пользователями.
Регулярное выражение, определенное ниже, будет соответствовать:
[a-zA-Z]
— один или несколько алфавитов (как в нижнем, так и в верхнем регистре)
,
— буквальный символ запятой
d{1,3}
— диапазон от 1 до 3 цифр. $
должно заканчиваться цифрой
import re
# input_text_sample = 'john,24'
input_pattern = re.compile(r'[a-zA-Z] ,d{1,3}
)
correct_input = None
while not correct_input:
user_input = input("Type 'Name,Age': ")
correct_input = input_pattern.match(user_input)
if not correct_input:
print("Incorrect try again")
else:
print(correct_input.string)