Python string index out of range error? - python

I'm attempting to convert names from a first name first style to a family name first. The trick is getting it to accept input with or without a middle name.
My code as it stands:
import re
def convertName(oldName):
newName = oldName
while newName == oldName:
newName = re.sub('^ +', '',oldName)
newName = re.sub(' +', ' ',newName)
return newName
def main(firstName, middleName, lastName):
finalName = (lastName + firstName + middleName)
return finalName
name = 0
while name != "":
name = str(input("Name ---- "))
if name == "":
print("Finished")
break
newName = convertName(name)
firstNameSplit = newName.find(" ")
firstName = newName[:firstNameSplit]
lastNameSplit = newName.rfind(" ") + 1
lastName = newName[lastNameSplit:] + ', '
middleNameSplit = newName[firstNameSplit:lastNameSplit]
middleName = middleNameSplit.strip()
finalMiddleName = " " + middleName[0] + '.'
finalName = main(firstName, finalMiddleName, lastName)
print("Result --",finalName)
print()
My current results:
Name ---- joshua example example
Result -- example, joshua e.
Name ---- joshua example
Traceback (most recent call last):
line 37, in 0
builtins.IndexError: string index out of range
Any tips/hints would be much appreciated!!
Eventually found out a working solution in the following:
newName = convertName(name)
firstNameSplit = newName.find(" ")
firstName = newName[:firstNameSplit]
lastNameSplit = newName.rfind(" ") + 1
lastName = newName[lastNameSplit:] + ', '
middleNameSplit = newName[firstNameSplit:lastNameSplit]
middleName = middleNameSplit.strip()
if middleName != "":
finalMiddleName = " " + middleName[0] + '.'
else:
finalMiddleName = ""
finalName = main(firstName, finalMiddleName, lastName)
print("Result --",finalName)
print()

Or you could just do the following:
name = str(input("Name ---- "))
if len(name.split()) == 2:
print("Result -- " + name[name.rfind(" "):] + ", " + name[:name.find(" ")] + " " + name[name.find(" ")+1] + ".")
if len(name.split()) == 1:
print ("Result -- " + name[name.find(" "):] + ", " + name[:name.find(" ")])
else:
print ("Sorry! Invalid name")
This implementation has only been tested in Python 2.7.5.
It uses the string methods .find() and .rfind() to find the indices of the start of the first name, middle name, and last name
len(name.split()) tests how many words are in the name.

Your problem:
string = ""
print(string[0])
returns an error.
so, I fixed your main function, but you'll have to re-write the parser:
def main(firstName, lastName, middleName=""):
if(middleName == ""):
finalName = (lastName + " " + firstName)
else:
finalName = lastName + " " + firstName + " " + middleName[0] + "."
return finalName

Related

How can i properly use dox import

i want to get info from the internet from a name (string) but its not working, here is my code:
import dox
AutoProccesFromPcName = dox:Resolve_name_of_base("Google Chrome.exe")
def FindInfo(name):
compose = dox.name(name)
netGlobalSearch = dox:FindMatchesForNetwork(AutoProccesFromPcName,compose)
numberOfResults = dox:ComposeFNumFrom(netGlobalSearch)
if numberOfResults > 0:
print("FOUND " + str(numberOfResults) + " RESULTS")
for index, result in netGlobalSearch:
if dox:PackInfo(dox:Compose(result)) != 0:
print("RESULT " + str(result) + " FOUND AT INDEX: " + str(index))
input("Press enter to exit program... ")

How can I refactor this python script better?

I am expected to ensure the code is written without unnecessary lines of code. Is there a way to refactor this and get the same output?
def format_name(first_name, last_name):
if len(first_name) > 0 and len(last_name) > 0:
return("Name: " + last_name + ", " + first_name)
elif len(first_name) > 0 or len(last_name) > 0:
return("Name: " + first_name + last_name)
else:
empty_string = ""
return empty_string
return string
print(format_name("Ernest", "Hemingway"))
# Should return the string "Name: Hemingway, Ernest"
print(format_name("", "Madonna"))
# Should return the string "Name: Madonna"
print(format_name("Voltaire", ""))
# Should return the string "Name: Voltaire"
print(format_name("", ""))
# Should return an empty string
Without getting "too golfie", this should do the trick:
def format_name(first_name, last_name):
name = f"{first_name}, {last_name}".strip(", ")
return f"Name: {name}" if name else ""
The refactored method tries to allocate the logic of the function in a single if condition.
def format_name(first_name, last_name):
result = ''
sep = ', ' if first_name and last_name else ' '
if first_name or last_name:
result = last_name + sep + first_name
result = 'Name: ' + result.strip()
return result
print(format_name("Ernest", "Hemingway")) # "Name: Hemingway, Ernest"
print(format_name("", "Madonna")) # "Name: Madonna"
print(format_name("Voltaire", "")) # "Name: Voltaire"
print(format_name("", "")) # `empty_string`
Use str.join and filter to build the name string:
def format_name(first_name, last_name):
full_name = ", ".join(filter(None, (last_name, first_name)))
if full_name:
full_name = "Name: " + full_name
return full_name

getting a blank string from output

I am having a hard time with understanding whats going on with this piece of code. the goal is to output a blank string if both of the names are missing. my code just outputs "Name: " no matter what i use for a return value????
def format_name(first_name, last_name):
if len(first_name) and len(last_name) !=0:
return "Name: " + str(last_name) +", " + str(first_name)
elif len(last_name) == 0:
return "Name: " + str(first_name)
elif len(first_name) == 0:
return "Name: " + str(last_name)
else:
return ""
The problem is that if both strings are empty, then one string is empty, too. You have to re-arrange your conditions or the last one will never be triggered. Also, but unrelated to the problem, you can just check if string to check whether string is non-empty. Also, no need to convert the names to str (assuming that they are str already).
def format_name(first_name, last_name):
if first_name and last_name: # both
return "Name: " + last_name +", " + first_name
elif not (first_name or last_name): # neither
return ""
elif last_name: # not both or neither, so only first
return "Name: " + last_name
else: # not both, neither, or first, so only last
return "Name: " + first_name
For less if/elif "fun", you could filter and join the non-empty names, if any:
def format_name(first_name, last_name):
present = [x for x in (last_name, first_name) if x]
if present:
return "Name: " + ", ".join(present)
else:
return ""
(The logic of that second one is also much simpler, as evident by the several mistakes I made in the first version, and less code-duplication, too.)
I made a format_name function on my own. Please test it. I'd be very happy if you let me know opinion.
def format_name(first_name, last_name):
name_list = [last_name, first_name]
name_list = [name.strip() for name in name_list if name.strip()]
full_name = ", ".join(name_list).strip()
if full_name:
return "Name: " + full_name
else:
return ""
first_name = ""
last_name = ""
full_name = format_name(first_name, last_name)
print(full_name)
You will need to rearrange the conditions to be able to check if both parts of the name are empty before you check for each individually.
def f_n(first_name, last_name):
if len(first_name) != 0 and len(last_name) !=0:
return "Name: " + str(last_name) +", " + str(first_name)
elif len(last_name) == 0 and len(first_name) == 0:
return " "
elif len(last_name) == 0:
return "Name: " + str(first_name)
else:
return "Name: " + str(last_name)
def format(first_name, last_name):
if len(first_name) != 0 and len(last_name) !=0:
return "Name: " + str(last_name) +", " + str(first_name)
if len(last_name) == 0 and len(first_name) == 0:
return " "
if len(last_name) == 0:
return "Name: " + str(first_name)
if len(first_name) == 0:
return "Name: " + str(last_name)

Python: Calling a function with a string returns the description of the argument

I am trying to call a function with a string but as I do so the function just make use of the name of the argument for that function.
My function is defined as sortering(attribut) and when i call it with for example: sortering('age') it uses 'attribut' and not 'age'.
Here is the code, I am fairly new to python so it is probably something obvious that I am not familiar with.
def sortering(attribut):
try:
val1 = input("Vill du sortera stigande eller fallande? s/f")
if val1 == "s":
djurlista.sort(key=lambda x: x.attribut)
print(*djurlista,sep='\n' + ' ' + '\n')
elif val1 == "f":
djurlista.sort(key=lambda x: x.attribut, reverse=True)
print(*djurlista,sep='\n' + ' ' + '\n')
except ValueError:
print("Svara med s för stigande eller f för fallande!")
sortering('age')
The list "djurlista" is a list of strings and each string is an object 'Djur' with attributes: art, namn, ålder, kön, gravid
Here is that code:
class Djur:
def __init__(self, art, namn, ålder, kön, gravid):
self.art = art
self.namn = namn
self.age = ålder
self.gender = kön
self.gravid = gravid
x = Djur(art, namn, ålder, kön, gravid)
self.djurlista.append(x)
def __str__(self):
return ("Art: " + str(self.art) + " " + "\n"
"Namn: " + str(self.namn) + " " + "\n"
"Ålder: " + str(self.age) + " " + "\n"
"Kön: " + str(self.gender) + " " + "\n"
"Gravid: " + str(self.gravid))
def __repr__(self):
return str(self)
Instead of x.attribut (where attribut is a string, and x is a Djur instance), you should use [Python 3.Docs]: Built-in Functions - getattr(object, name[, default]):
djurlista.sort(key=lambda x: getattr(x, attribut))
Use x[attribut] and not x.attribut
def sortering(attribut):
try:
val1 = input("Vill du sortera stigande eller fallande? s/f")
if val1 == "s":
djurlista.sort(key=lambda x: x[attribut])
print(*djurlista,sep='\n' + ' ' + '\n')
elif val1 == "f":
djurlista.sort(key=lambda x: x[attribut], reverse=True)
print(*djurlista,sep='\n' + ' ' + '\n')
except ValueError:
print("Svara med s för stigande eller f för fallande!")
sortering('age')
It appears that you're trying to get the .attribut parameter from a global class/obj called x (via x.attribut), which should be throwing an error if it doesn't exist, but may not be if it's stored in your python cli somehow.
If you remove the x. before the reference to attribut, do you still get the same error?

Why is my code getting this ValueError when it's automarked?

So, my code is based of a module in a learning site which I use called Grok, these are the requirements which I had to create in order to pass to the next stage
The Requirements (left-hand-side of photo) and Auto Marker Error (bottom right handside)
The error in question is;
Testing a longer case with many letters. Your submission raised an exception of type ValueError. This occurred on line 4 of program.py.
I can't seem to figure out how to fix this to get it marked correctly, yet my code works pretty much perfectly.
My code
import collections
collect = collections.defaultdict(list)
order = input('Name: ')
name, surname = order.split(' ', 1)
collect[surname].append(name)
mail = open('mail.txt', encoding="UTF-8").read()
mail = mail.split('\n')
letter = 0
package = 0
count = mail.count(' '.join(collect[surname]) + ' ' + surname + ',Letter')
count2 = mail.count(' '.join(collect[surname]) + ' ' + surname + ',Package')
for i in collect:
if (' '.join(collect[surname]) + ' ' + surname + ',Letter') in mail:
letter += 1 * count
if (' '.join(collect[surname]) + ' ' + surname + ',Package') in mail:
package += 1 * count2
if package == 0 and letter == 0:
print("No mail")
if letter > 1:
print(count, "Letters")
if letter == 1:
print(count, "Letter")
if letter == 0 and package != 0:
print("No Letters")
if package > 1:
print(count2, "Packages")
if package == 1:
print(package, "Package")
if package == 0 and letter != 0:
print("No Packages")
There is only one space in the second line of the example for the third input in the screenshot.
For line 4 (name, surname = order.split(' ', 1)), the tuple unpacking will raise a ValueError if there's no space in order.
EDIT:
order = input('Name: ')
# was name, surname = order.split(' ', 1)
try:
name, surname = order.split(' ', 1)
except ValueError:
name, surname = order, ""
collect[surname].append(name)

Categories

Resources