Creating User Name from Name in Python - python

I have a spreadsheet with data. There I have a name like Roger Smith. I would like to have the user name rsmith.
Therefore, the first letter of the first name followed by the family name. How can I do this in Python?

def make_username(full_name: str) -> str:
first_names, last_name = full_name.lower().rsplit(maxsplit=1)
return first_names[0] + last_name
print(make_username("Roger M. Smith"))
Output: rsmith
The use of rsplit is to ensure that in case someone has more than one first name, the last name is still taken properly. I assume that last names will not have spaces in them.
Note however that depending on your use case, you may need to perform additional operations to ensure that you don't get duplicates.

By passing the 0 index to the full name we get the first letter of the name.
Using the split() function we can convert the full_name into list. Then passing -1 index we can get the family name.
Lower() will convert the name into lower case.
full_name = 'Roger Smith'
username = full_name[0] + full_name.split()[-1]
print(username.lower())
#output : rsmith

Here's an option in case you are also interested in generating usernames using last name followed by first letter of first name:
name = 'Roger R. Smith'
def user_name_generator(name,firstlast = True):
username = name.lower().rsplit()
if firstlast:
username = username[0][0] + username[-1]
else:
username = username[-1] + username[0][0]
return username
This outputs rsmith if the parameter firstlast is set to True and outputs smithr if firstlast is set to False

if I understand your question correctly, you want to iterate through all the names of an excel sheet in the format 'firstletternamesurname'. This can be done with pandas, but I don't know if that's exactly what you want. With pandas there will be a final dataframe and you can export it to excel again. Try this:
import pandas as pd
df = pd.read_excel('name.xlsx')
for i in df:
df1 = df['name'].iloc[0] + df['surname'].iloc[0]
df2 = df1.split()[0]
print(df2.lower())

Related

How to use sep parameter in .format?

I just started learning python and I'm experimenting new things.
isim = input("Name:")
soyad = input("Surname:")
yaş = input("Age:")
edu = input("Education:")
gen = input("Gender:")
print("Name: {},Surname: {},Age: {},Education: {},Gender: {}".format(
isim,soyad,yaş,edu,gen))
My aim is to use \n after all brackets ({}) so I'll be able to print them more organised but I don't want to use \n after every part.
print(a,b,c,d,e,sep = \n)
is the only way I know. I want to use sep and format together. How can I do that?
You're only printing one string created by using format so sep doesn't apply. You could expand a generator expression that adds "\n" to each argument to format, though.
print("Name: {},Surname: {},Age: {},Education: {},Gender: {}".format(
*(f"{x}\n" for x in [isim,soyad,yaş,edu,gen])))
You may instead wish to use a multi-line f-string, though.
print(f"""Name: {isim}
Surname: {soyad}
Age: {yaş}
Education: {edu}
Gender: {gen}""")
Personally, I'd just format your print statement like:
print(f"Name: {isim}",f"Surname: {soyad}",f"Age: {yaş}",f"Education: {edu}",f"Gender: {gen}", sep='\n')
# OR
print(f"Name: {isim}\nSurname: {soyad}\nAge: {yaş}\nEducation: {edu}\nGender: {gen}")
As an alternative to #Chris's comprehensive answer, you can simply apply replace before formatting your string:
print("Name: {},Surname: {},Age: {},Education: {},Gender: {}".replace('{}', '{}\n').format(isim,soyad,yaş,edu,gen))
A systematical approach which depends entirely on the type of field entries. Data stored into dictionary, then a single string is constructed using format and join.
# fields names
fields = ("Name",
"Surname",
"Age",
"Education",
"Gender")
# used a dictionary to store the input results
data = {field: input(field) for field in fields}
# key-value template
template_string = '{}: {{}}'
# add the keys
field_names = map(template_string.format, data)
# add the values (with separator ",\n")
result = ',\n'.join(field_names).format(*data.values())
# check result
print(result)
Another similar way could be to use the "var=" property of f-strings. Requirement: the variables identifiers should be chosen properly since they will part of the final string. Side-effect: there are = around... if no conflicts they can be substituted with
Name = input("Name:")
Surname = input("Surname:")
Age = input("Age:")
Education = input("Education:")
Gender = input("Gender:")
# var= property of f-string
result = f'{Name=}\n{Surname=}\n{Age=}\n{Education=}\n{Gender=}'
# if no conflicts with = symbol
result = result.replace('=', ': ')
print(result)
How to use format and sep together? Taking as reference the approach in the question: a list is required, if no conflicts with other characters, split it at ,:
# ...
result = "Name: {},Surname: {},Age: {},Education: {},Gender: {}".format(isim,soyad,yaş,edu,gen)
print(*result.split(','), sep='\n')

Validate list of last names of Hotel Guests according to the corresponding first name in a text file in Python

I have a text file called listofhotelguests.txt where hotelguests are stored line by line with their first names separated by && as a delimiter. Can someone explain how I can have my Python program read it so it associates john with doe, ronald with macdonald, and george with washington?
My expected outcome I'm hoping for is if I prompt the user for their lastname to make sure their a valid guest on the list, the program will check it against what it has in the file for whatever the firstname they entered earlier was.
So if someone enters george as their first name, the program retrieves the line where it has george&&washington, prompts the user to enter their lastname and if it doesn't match what it has, either say it matches or doesn't. I can figure the rest out later myself.
Assuming there is nobody with the same names.
I know I have to split the lines with &&, and somehow store what's before && as something like name1 and whats after && as name2? Or could I do something where if the firstname and lastname are on the same line it returns name1 and password1?
Not sure on what to do. Python is one of my newer languages, and I'm the only CS student in my family and friend groups, so I couldn't ask anybody else for help. Got nowhere by myself.
Even just pointing me in the direction of what I need to study would help immensely.
Thanks
Here's what the text file looks like:
john&&doe
ronald&&macdonald
george&&washington
abraham&&lincoln
Here's some pseudocode:
listoffirstnames = []
listoflastnames= []
with open ("listofhotelguests.txt") as guestlist:
for line in guestlist
listoffirstnames.append()
listoflastnames.append()
while True:
firstname = input("Please enter your firstname")
if (firstname in listoffirstnames):
print("Hello" ,firstname)
break
else:
print("Sorry, you weren't in the list. Please try again")
while True:
print("Hello " + firstname + " please enter your last name.")
lastname = input("Enter lastname to verify guest status: ")
if (lastname in listoflastnames):
print("Welcome back!" + firstname + lastname)
break
else:
print("Sorry, the lastname was entered wrong")
Here's a solution:
first_names = []
last_names = []
with open("bruh.txt") as f:
for line in f:
name = line.strip().split("&&")
first_names.append(name[0])
last_names.append(name[1])
print(first_names)
print(last_names)
Basically, strip() removes any pesky unwanted spaces on either end, and the split() function allows you to split a string based on the parameter, here &&. So name ends up storing the first and last name as a list, and you can access them through subscripts.
That said, a long-term better solution would be to store both the first and last names together as a list, inside a bigger list of all names. For example,
names = [['john', 'doe'], ['firstname', 'lastname'], ...]
For that you can use this:
names = []
with open("bruh.txt") as f:
for line in f:
name = line.strip().split("&&")
names.append(name)
print(names)
Which outputs: [['john', 'doe'], ['ronald', 'macdonald'], ['george', 'washington'], ['abraham', 'lincoln']]
Admittedly, this does require more code to access all first and last names separately, but as I said, the convenience of having both parts of the name as part of a single list of names is a better long term approach.

How to sub-string a list in Python

I have an assignment where I have a list with two names and I have to print the first name and then I have to print the last name.
names_list = ['Oluwaferanmi Fakolujo', 'Ajibola Fakolujo']
I have two names and then when I find the whitespace between them I have to print both the first name and the last name out of the list and put it into a variable.
I have tried to slice it but I don't understand it enough to use it. Here is an example:
substr = x[0:2]
This just brings both names instead of only substring it.
names_list = ['Oluwaferanmi Fakolujo', 'Ajibola Fakolujo']
for i in range(0, len(names_list)):
nf = names_list[i].split(' ')
name = nf[0]
family = nf[1]
print("Name is: {}, Family is: {}".format(name, family))
Output:
Name is: Oluwaferanmi, Family is: Fakolujo
Name is: Ajibola, Family is: Fakolujo
This will only work for Python 3.x
You can use the split() method and indexing for these kinds of problems.
Iterate through the list
split() the string
Store the values in a variable, so that we can index them
Display the values
names_list = ['Oluwaferanmi Fakolujo', 'Ajibola Fakolujo']
for i in names_list:
string = i.split(" ")
first_name = string[0]
last_name = string[1]
print(f"First Name: {first_name} Last Name: {last_name}")

Integrating Wildcard In Comparison of Strings

I have a python script which takes a name, re-formats it, and then compares it to a list of other names to see how many times it matches. The issue is the names it is being compared to have middle initials (which I don't want to have entered in the script).
list_of_names = ['Doe JM', 'Cruz CR', 'Smith JR', 'Doe JM', 'Maltese FL', 'Doe J']
Now I have a simple function that reformats the name.
f_name = name_format('John','Doe')
print(f_name)
> 'Doe J'
Now I want to do comparisons where everytime "Doe J" or "Doe JM" appears, the value is true. The below function would not work as intended.
def matches(name, list):
count = 0
for i in list:
if i == name:
count = count + 1
else:
pass
return(count)
print (matches(f_name, list_of_names))
> 1
My goal is to make the return equal to 3. To do these, I want ignore the middle initial which in this case would be 'M' in 'Doe JM'.
What I want to do is something along the lines of formatting the name to 'Doe J?' where '?' is a wild card. I tried importing fnmatch and re to use some of their tools but was unsuccessful.
Use two for and yield. Function will return duplicate values and you need use set for remove it:
list_of_names = ['Doe JM', 'Cruz CR', 'Smith JR', 'Doe JM', 'Maltese FL', 'Doe J']
# List of names
def check_names(part_names, full_name_list):
for full_name in full_name_list:
for part_name in part_names:
if part_name in full_name:
yield full_name
result = set(check_names(['Doe J', 'Cruz'], list_of_names))
# One name
def check_names(name, full_name_list):
for full_name in full_name_list:
if name in full_name:
yield full_name
result = check_names('Doe J', list_of_names)
print list(result) # List of result
print len(result) # Count of names
You were on the right track with the re module. I believe the solution to your problem would be:
import re
def matches(name, name_list):
regex = name + '\w?' # Allows one addition word character after the name
result = list(map(lambda test_name: re.match(regex, test_name) is not None, name_list))
return result.count(True)
print(matches(f_name, list_of_names))
# 3
This solution ensures that exactly one alphanumeric character is allowed after the name.

How to split a string on a character that occurs more than once inside the string

I am having a some logic issues attempting to parse a string into two fields. Name and Version. I have been splitting on "/" and it works very well for strings that have only one "/" in them. for example:
strString = someName/A
nameVer = strString .split('/')
name = nameVer[0]
ver = nameVer[1]
this returns name=someName and ver=A. Which is what i want. The problem is when i have more than one "/" in the string. Particularly this 3 cases:
Part ="someName//" #Expected output: name=someName ver=\
Part1="some/Name/A" #Expected output:name=some/Name ver=A
Part2="some/Name//" #Expected output:name=some/Name ver=/
Both the name and version can be or contain "/"'s. I have tried many things including keeping track of the indexes of the "/" and grabbing whats in between. In some cases I have also added brackets to the string ("[some/Name//]") so i can index the first and last char of the string. Any help with this is greatly appreciated. Thanks
Following some useful comments by BrenBarn and sr2222, I suggest the following solutions.
The OP should either
Make sure that the version string does not contain any '/' characters, and then use rsplit as suggested by sr2222
or
Choose a different delimiter for for the name-version division
A solution that ignores the last character (such that it can be assigned to the ver variable) would be
ind = Part[:-1].rindex('/')
name = Part[:ind+1]
ver = Part[ind+1:]
On the OPs inputs this produces the desired output.
If any instance of the separator might be doing the separating, there are too many choices. Take your last example, some/name//. Which of the three slashes is the
separator? The string can be parsed, in order, as ("some", "name//"),
as ("some/name", "/"), or as ("some/name/", "").
What to do? Let's say the version is necessarily non-empty (ruling out option 3),
and otherwise the name part should be maximal. If you like these rules,
here's a regexp that will do the job: r'^(.*)/(.+)$'. You can use it like this:
name, ver = re.match(r'^(.*)/(.+)$', "some/name/").groups()
Here's what it does:
>>> re.match(r'^(.*)/(.+)$', "name//").groups()
('name', '/')
>>> re.match(r'^(.*)/(.+)$', "some/name/a").groups()
('some/name', 'a')
>>> re.match(r'^(.*)/(.+)$', "some/name//").groups()
('some/name', '/')
>>> re.match(r'^(.*)/(.+)$', "some/name/").groups()
('some', 'name/')
In short, it splits on the last slash that has something after it (possibly a final slash). If you don't like this approach, you'll need to provide more detail on what you had in mind.
For the cases you've posted, this would work:
if part.endswith('//'):
name, ver = part[:-2], '/’
else:
name, ver = part.rsplit(’/’, 2)
Here is the code I made that handles just about every case. The only cases that it does not handle is when the name and version is ambiguous and you cannot tell if a "/" is apart of the name or ver. Thank you for everyone's input.
Part ="[0717_PFM1//]"
Part1="[0717_PFM1/A]" #generic case
Part2="[0717/_PFM1/A]"
Part3="[07/17/_PFM1//]" #Test case below
#Part3="[0717/_PFM1//B]" #Not working, ambigous: cant tell if the ending slash is part of name or ver
import re
lastCharIndex = Part3.index(']')
list1 =[]
counter = 0
numberOfSlashes = Part3.count("/")
if numberOfSlashes > 1:
nameVer = Part3.split("/")
name1, ver1 = re.match(r'^(.*)/(.+)$', Part3).groups()
if nameVer[2].strip("]") or ver1.strip("]") == "":
ver = "/"
else:
ver = nameVer[2].strip("]")
name = nameVer[0].strip('[')
if len(name1)>len(name):
name = name1
if len(ver1) > len(ver):
ver = ver1
name = name.rstrip("/")
else:
nameVer = Part3.split("/")
name, ver = nameVer[0], nameVer[1]
print "name",name.strip('['), "ver",ver.strip(']')

Categories