0

Hi I could use some pointers with my code at the bottom of this post. (I started learning Python Recently btw, so any feedback even if it doesn't relate entirely to the question is much appreciated)

So Basically my code needs to do/factor in the following:

  1. Print out someone's userID based on their first and last name.
  2. The userid cannot be > 8 characters total
  3. The first 2 characters of the first name are to be used followed by the last 6 of the surname.

Everything works as I want it to for names such as:

John Doe = "jodoe"
Marie Anne Richardson = "maardson"

But it all changes when we look at examples such as:

J.K.Rowling = "j.owling"
John D O E = "jod o e "

I don't want to allow the usage of punctuation and integers and I am unable to control whitespace in between characters. In some contexts first names will be something like "Marie Anne" or people may have multiple last names, so whitespace in between should definitely be allowed as user input but what I'm looking for is to have it stripped.

So the user can type "Marie Anne Richardson" and this will still allow user "maardson". However:

"John D O E" would result in "jodoe". "John Doe Doe" would result in "jodoedoe"

Code:

print(
    "Welcome to the UserID Tool, a few questions will be asked to generate your Unique UserID"
)
prompt = ">"
first_name = input(f"What is your First Name?\n{prompt}").lower().strip()
last_name = input(f"What is your Last Name\n{prompt}").lower().strip()

len_first_name = len(first_name)
len_last_name = len(last_name)
max_userid_len = 8

if len_first_name + len_last_name > max_userid_len:
    new_last_name = last_name[-6:].strip()
    print(f"Your user id is {first_name[0:2]}{new_last_name}")
else:
    print(f"Your user id is {first_name[0:2]}{last_name}")
martineau
  • 119,623
  • 25
  • 170
  • 301
Tiago Mendes
  • 7
  • 1
  • 3
  • You could try removing punctuation as showed in the following link https://www.tutorialspoint.com/How-to-strip-down-all-the-punctuation-from-a-string-in-Python and then replace whitespaces with .replace(" ", "") – lsabi Mar 15 '20 at 17:34
  • What is ```J.K.Rowling``` supposed to generate? Maybe you want some kind of user input screening before trying to process the string? – neutrino_logic Mar 15 '20 at 17:35
  • thank you! The replace function is definitely better than what I have, but it doesn't stop users from typing in other symbols by mistake or intentionally. I think that creating a function as shown by neutrino_logic below would be the way to go about this. – Tiago Mendes Mar 15 '20 at 18:13

4 Answers4

1

I suggest you use the replace() function for your purpose.

You can write: new_first_name = first_name.replace(".", "")

To replace multiple substrings you should use a dictionary as in this example: How to replace multiple substrings of a string?

picklepirate28
  • 143
  • 1
  • 1
  • 10
  • Thank you datalee, the replace would be an improvement, although it doesn't restrict the user entirely from what I understood. As for using a dictionary, I have no idea what that is, gotta learn about that first before I can comment anything intelligent about it. – Tiago Mendes Mar 15 '20 at 18:18
1

For a clean regex solution - I would do:

import re

sample_=["John Doe", "J.K.Rowling",  "Marie Anne Richardson", "John D O E", "John Doe Doe"]
res=""
for el in sample_:
    print(f"BEFORE: {el}")
    res=re.sub(r"[^a-z\s]", "", el.lower().strip())
    res=re.sub(r"(?<=\s)([^\s]*)\s", r"\1", res)
    res=re.sub(r"(^[a-z]{1,2}).{0,}?([a-z]{1,6})$", r"\1\2", res)
    print(f"AFTER: {res}")

Outputs:

BEFORE: John Doe
AFTER: jodoe
BEFORE: J.K.Rowling
AFTER: jkowling
BEFORE: Marie Anne Richardson
AFTER: maardson
BEFORE: John D O E
AFTER: jodoe
BEFORE: John Doe Doe
AFTER: jodoedoe

What's happening there:

First 2 re.sub(...) are just to get rid of all non-letter characters, except the first inside-string space (so you can for sure distinguish what's the first word of first name - to get top 1-2 characters).

Second one: "(^[a-z]{1,2}).{0,}?([a-z]{1,6})$" pulls:

(1) (group 1 - due to square brackets) (^[a-z]{1,2}) matches up to the first two letters of the string, whereas it's a greedy operator so it will match all 2, if there are 2.

(2) inner part: .{0,}? matches any number of characters, while being non-greedy (that's what question mark indicates) - hence it will match as little as possible.

(3) (group 2 - due to square brackets) ([a-z]{1,6})$ will match up to 6 last characters from the end, whereas again it's a greedy operator, hence it will match a much as possible.

The whole string matched that way we replace with group 1 and group 2 (hence we drop the inner part).

Some ref to python regex lib: re:

https://docs.python.org/3.5/library/re.html

Grzegorz Skibinski
  • 12,624
  • 2
  • 11
  • 34
0

Maybe use .replace() function. If you are only concerned about “.” and “ “ you can utilize those few lines:

name = input(“Tell the name”)
name1 = name.replace(".", "")
name2 = name1.replace(“ “,””)
szafran
  • 55
  • 1
  • 11
  • Hi Szafran, thank you for your reply, again it would be an improvement over what I have, and was good for me to learn about the replace method but it I'd need a bunch of those to stop a user from inserting anything that aren't letters. – Tiago Mendes Mar 15 '20 at 18:20
0

It often makes sense to create a function to screen input, such as:

def get_input(query):
    while True:     #endless loop broken by return of acceptable input
        acceptable = True
        foo = input(query)
        for x in foo:
            if not(x.isalpha() or x.isspace()): #positive selection
                print("No numbers or punctuation allowed")
                acceptable = False
                break
        if len(foo.split()[0]) < 2:    #first word length check
            print("First name must have at least two letters")
            acceptable = False
        if acceptable:   #break up string, erase all whitespace, insert
                         #one whitespace after first name, return
            return foo.split()[0] + ' ' + ''.join(foo.split()[1:])   

Then you can simply call this function with the question as the query, for every input. This guarantees every string returned from the function will only have one whitespace between two alphabetical strings.

neutrino_logic
  • 1,289
  • 1
  • 6
  • 11
  • Thanks for this, I tried it out and it seems to work, except with First Name : John and Last Name: Doe Doe I still haven't learned about creating your own functions but I got this code to run and give me something, so it helped at least in gaining a vague understanding of how this works which is positive! – Tiago Mendes Mar 15 '20 at 18:09
  • That function is set for entering the name in one line, try ```John Doe Doe```. It shouldn't be to hard to edit it to strip all whitespace however (just take out the space ```' '``` in the return statement. – neutrino_logic Mar 15 '20 at 19:33