1

I want to only allow a user to input a string followed by an integer and separated using a comma and if they do not comply I would like to let them know that they have inputted incorrectly and to let them try again. I am having trouble finding a way to do this, I can make the input require a comma but I do not know how to specify a string and int on each side.

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 & 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")
2
  • could you provide an example of a valid string? Commented Mar 31, 2021 at 11:32
  • @collinsuz 'john,24' Commented Mar 31, 2021 at 11:36

4 Answers 4

2

you can for example make a function to validate the user input, like this. Here's an example, it's working, but you have to make some modifications.

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 & 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")


Sign up to request clarification or add additional context in comments.

1 Comment

Man I tried anding earlier tonight and couldn't get it done, seeing your example helped a lot, I plugged the 'if and not' into my code and was able to drop the exception, thankyou! if decomposed_string[1].isdigit() and not decomposed_string[0].isdigit():
1

Regex patterns suits very well for this kind of simple string parsing. Other solution in complex cases would be to go for some third party library PyParsing or Parsley.

With regex groups and especially named groups are very handy. Here's a simple example:

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')

Then some extra hints. To make your code a little bit more pythonic you could use some classes. Here's a sample:

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 Comment

Thankyou very much, I haven't gotten to regex or classes yet but once I do I will be sure to look back over this and try to rewrite this program more efficiently using this for some practice and learning, thanks for your time!
0

Here I have used a regex for your condition to validate the input:

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 & 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")

So this regex would accept names with spaces example "anosha rehan, 12" but if you're looking for only one word names so use this regex '(\w+)*,\d+'

Comments

0

You can use regex to match the exact pattern you want from users input.

The regex defined below would match:

[a-zA-Z]+ - one or more alphabet (both lower and upper case)

, - literal comma character

\d{1,3} - a range between 1 to 3 digits. $ must end in digit

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)

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.