Python Zybooks LAB 9.6 - Contact List - python

Yet again, I do not understand an error I keep encountering. Here is my code:
s = input()
name = input()
splits = s.split(" ")
i = 0
for i in range(len(splits)):
if(splits[i] == name):
break
print(splits[i+1])
Here is the error:
Traceback (most recent call last):
File "main.py", line 15, in <module>
print(splits[i+1])
IndexError: list index out of range
I am not sure why [i+1] returns as out of range. What did I screw up this time? I appreciate the help in advance as I don't get much guidance from my instructor or TA. You folks rock here!
Edit: I apologize I did not include a desired outcome.
The input is:
Joe,123-5432 Linda,983-4123 Frank,867-5309
Frank
The output is supposed to be:
867-5309

s = 'Hello'
name = 'Goodbye'
splits = s.split() # default value is a single space ['Hello'] - notice the single value
for i in range(1): # because splits has a single item in the list
if 'Hello' == 'Goodbye':
break
print(splits[i+1]) # this will not work because splits has a single index = 0
# same as
s = [0,1]
print(s[2])
I advise to come up with a desired output when you are asking a question on StackOverflow so others will have a better understanding of your problem.
Also, as mentioned by Hossein in the comment, try using print() in each line of your code to see if you get what you expect.
-- Update --
s_input = 'Joe,123-5432 Linda,983-4123 Frank,867-5309'
to_search = 'Frank'
# split the input
splitted_input = s_input.split()
for item_pair in splitted_input:
# split the pair by a comma
pair_split = item_pair.split(',')
name = pair_split[0]
number = pair_split[1]
if name == to_search:
print(name, number)
Frank 867-5309
The problem you had is that after you split you have 3 elements but I assume you have thought you get 6, 3 pairs for a name and a number, therefore when you try to reach the number you get out of index, you need to split by a comma to separate the people one from another and then split again to separate the number from the name.
But I would suggest to use:
def find_number(string_to_search, name_to_find):
splits = string_to_search.split()
for item in splits:
if name_to_find.lower() in item.lower():
return item.split(',')[1]
find_number('Joe,123-5432 Linda,983-4123 Frank,867-5309', 'Frank')
# '867-5309'

Related

Read a file line by line, subtract each number from one, replace hyphens with colons, and print the output on one single line

I have a text file (s1.txt) containing the following information. There are some lines that contain only one number and others that contain two numbers separated by a hyphen.
1
3-5
10
11-13
111
113-150
1111
1123-1356
My objective is to write a program that reads the file line by line, subtracts each number from one, replaces hyphens with colons, and prints the output on one single line. The following is my expected outcome.
{0 2:4 9 10:12 110 112:149 1110 1122:1355}
Using the following code, I am receiving an output that is quite different from what I expected. Please, let me know how I can correct it.
s1_file = input("Enter the name of the S1 file: ")
s1_text = open(s1_file, "r")
# Read contents of the S1 file to string
s1_data = s1_text.read()
for atoms in s1_data.split('\n'):
if atoms.isnumeric():
qm_atom = int(atoms) - 1
#print(qm_atom)
else:
qm_atom = atoms.split('-')
print(qm_atom)
If your goal is to output directly to the screen as a single line you should add end=' ' to the print function.
Or you can store the values in a variable and print everything at the end.
Regardless of that, you were missing at the end to subtract 1 from the values and then join them with the join function. The join function is used on a string where it creates a new string with the values of an array (all values must be strings) separated by the string on which the join method is called.
For example ', '.join(['car', 'bike', 'truck']) would get 'car, bike, truck'.
s1_file = input("Enter the name of the S1 file: ")
s1_text = open(s1_file, "r")
# Read contents of the S1 file to string
s1_data = s1_text.read()
output = []
for atoms in s1_data.split('\n'):
if atoms.isnumeric():
qm_atom = int(atoms) - 1
output.append(str(qm_atom))
else:
qm_atom = atoms.split('-')
# loop the array to subtract 1 from each number
qm_atom_substrated = [str(int(q) - 1) for q in qm_atom]
# join function to combine int with :
output.append(':'.join(qm_atom_substrated))
print(output)
An alternative way of doing it could be:
s1_file = input("Enter the name of the S1 file: ")
with open (s1_file) as f:
output_string = ""
for line in f:
elements = line.strip().split('-')
elements = [int(element) - 1 for element in elements]
elements = [str(element) for element in elements]
elements = ":".join(elements)
output_string += elements + " "
print(output_string)
why are you needlessly complicating a simple task by checking if a element is numerical then handle it else handle it differently.
Also your code gave you a bad output because your else clause is incorrect , it just split elements into sub lists and there is no joining of this sub list with ':'
anyways here is my complete code
f=open(s1_file,'r')
t=f.readlines()#reading all lines
for i in range(0,len(t)):
t[i]=t[i][0:-1]#removing /n
t[i]=t[i].replace('-',':') #replacing - with :
try:t[i]=int(t[i])-1 #convert str into int & process
except:
t[i]=f"{int(t[i].split(':')[0])-1}:{int(t[i].split(':')[1])-1}" #if str case then handle
print(t)

How to split a single line input string having Name(1 or more words) and Number into ["Name" , "Number"] in Python?

I am a newbie. I failed one of the test cases in a phone book problem. As per the question, a user is expected to enter a single line input which contains a name (which can be one or more words) followed by a number. I have to split the the input into ["name","number"] and store it in dictionary. Note that the name will have one or more words(Eg: John Conor Jr. or Apollo Creed). I am confused with the splitting part. I tried out the split() function and re.split(). Not sure I can solve this.
Sample input 1 : david james 93930000
Sample Input 2 : hshhs kskssk sshs 99383000
Output: num = {"david james" : "93930000", "hshhs kskssk sshs" : "99383000"}
I need to store it in a dictionary where the key:value is "david james": "93930000"
Please help. Thank you
=====>I found a solution<==========
if __name__ == '__main__':
N=int(input())
phonebook={}
(*name,num) = input().split()
name = ''.join(map(str,name)
phonebook.update({name:num})
print(phonebook)
The astrik method words. But for a large data set this might slow me down. Not sure.
So im assuming that the inputs stated are coming from a user, if that
is the case you could change the format in your code to something
similar to this. You can change the range depending on how many inputs you want.
name = {}
for i in range(5):
student_name = input("Enter student's name: ")
student_mark = input("Enter student's mark: ")
name[student_name.title()] = student_mark
print(marks)
This should print the results in the way you mentioned!
Please check for the updated answer if this is what you are looking
for.
# Sample text in a line...
# With a name surname and number
txt = "Tamer Jar 9000"
# We define a dictionary variable
name_dictionary = {}
# We make a list inorder to appened the name and surname to the list
name_with_surname = []
# We split the text and if we print it out it should look something like this
# "Tamer", "Jar", "9000"
# But you need the name and surname together so we do that below
x = txt.split()
# We take the first value of the split text which is "Tamer"
# And we take the second value of the split text us "Jar"
name = x[0]
surname = x[1]
# And here we append them to our list
name_with_surname.append(name + " " + surname)
#print(name_with_surname)
# Finally here to display the values in a dictionary format
# We take the value of the list which is "Tamer Jar" and the value of the number "9000"
name_dictionary[name_with_surname[0]] = x[2]
print(name_dictionary)
The above answers can't handle if a data has too many name parts in one line.
Try my code below.
You can just loop through whatever the total number of inputs you want.
phonebook = {}
total_inputs = int(input())
for i in range(total_inputs):
name_marks = input().split() # taking input and splitting them by spaces
name = " ".join(x for x in name_marks[:-1]) # extracting the name
marks = name_marks[-1] # extracting the marks
phonebook[name] = marks # storing the marks in the dictionary
This way you can store the marks for the name. It will handle even one input has many name parts.

Strip list items with multiple arguments error

I'm trying to remove a lot of stuff from a text file to rewrite it.
The text file has several hundred items each consisting of 6 lines of.
I got my code working to a point where puts all lines in an array, identifies the only 2 important in every item and deletes the whitespaces, but any further stripping gives me the following error:
'list' object has no attribute 'strip'
Here my code:
x = 0
y = 0
names = []
colors = []
array = []
with open("AA_Ivory.txt", "r") as ins:
for line in ins:
array.append(line)
def Function (currentElement, lineInSkinElement):
name = ""
color = ""
string = array[currentElement]
if lineInSkinElement == 1:
string = [string.strip()]
# string = [string.strip()]
# name = [str.strip("\n")]
# name = [str.strip(";")]
# name = [str.strip(" ")]
# name = [str.strip("=")]
names.append(name)
return name
# if lineInSkinElement == 2:
# color = [str.strip("\t")]
# color = [str.strip("\n")]
# color = [str.strip(";")]
# color = [str.strip(" ")]
# color = [str.strip("=")]
# colors.append(color)
# return color
print "I got called %s times" % currentElement
print lineInSkinElement
print currentElement
for val in array:
Function(x, y)
x = x +1
y = x % 6
#print names
#print colors
In the if statement for the names, deleting the first # will give me the error.
I tried converting the list item to string, but then I get extra [] around the string.
The if statement for color can be ignored, I know it's faulty and trying to fix this is what got me to my current issue.
but then I get extra [] around the string
You can loop through this to get around the listed string. For example:
for lst, item in string:
item = item.strip("\n")
item = item.strip(";")
item = item.strip(" ")
item = item.strip("=")
name.append(item)
return name
This will get you to the string within the list and you can append the stripped string.
If this isn't what you were looking for, post some of the data you're working with to clarify.
Alright, I found the solution. It was a rather dumb mistake of mine. The eerror occured due to the [] arroung the strip function making the outcome a list or list item. Removing them fixed it. Feeling relieved now, a bit stupid, but relieved.
You can also do that in one line using the following code.
item = item.strip("\n").strip("=").strip(";").strip()
The last strip will strip the white spaces.

What's wrong with populating a dictionary

I want to populate a dictionary newDict in following code:
def sessions():
newDict = {}
output = exe(['loginctl','list-sessions']) # uses subprocess.check_output(). returns shell command's multiline output
i = 0;
for line in output.split('\n'):
words = line.split()
newDict[i] = {'session':words[0], 'uid':words[1], 'user':words[2], 'seat':words[4]}
i += 1
stdout(newDict) # prints using pprint.pprint(newDict)
But it only keeps giving me error:
newDict[i] = {'session':words[0], 'uid':words[1], 'user':words[2], 'seat':words[4]}
IndexError: list index out of range
If I do print words in the loop, here's what I get:
['c3', '1002', 'john', 'seat0']
['c4', '1003', 'jeff', 'seat0']
What am I doing wrong?
I think, it is a typo:
You use words[4] instead of words[3].
BTW:
Here is a slightly improved version of your code. It uses splitlines() instead of split('\n') and skips empty lines. And it uses enumerate(), wich is a pretty neat function when it comes to counting entries while iterating over collections.
def sessions():
newDict = {}
output = exe(['loginctl','list-sessions']) #returns shell command's multiline output
for i, line in enumerate(output.splitlines()):
if len(line.strip()) == 0:
continue
words = line.split()
print words
newDict[i] = {'session':words[0], 'uid':words[1], 'user':words[2], 'seat':words[3]}
stdout(newDict) # prints using pprint.pprint(newDict)
Imo You should check if "words" isn't too short. It's most likely problem with list length after spliting some line (It has no enough elements) .
My best guess is that words, does not allways hold five items,
please try to print len(words) before assigning the dict.
As far as I can tell, this has nothing to do with the dictionary itself, but with parsing the output. Here is an example of the output I obtain:
SESSION UID USER SEAT
c2 1000 willem seat0
1 sessions listed.
Or the string version:
' SESSION UID USER SEAT \n c2 1000 willem seat0 \n\n1 sessions listed.\n'
This all appears on the stdout. The problem is -- as you can see - is that not every line contains four words (there is the empty line at the bottom). Or more pythonic:
>>> lines[2].split()
[]
You thus have to implement a check whether the line has four columns:
def sessions():
newDict = {}
output = exe(['loginctl','list-sessions']) # uses subprocess.check_output(). returns shell command's multiline output
i = 0;
for line in output.split('\n'):
words = line.split()
if len(words) >= 4:
newDict[i] = {'session':words[0], 'uid':words[1], 'user':words[2], 'seat':words[3]}
i += 1
stdout(newDict)
(changes highlighted in boldface)
In the code I've also rewritten words[4] to words[3].

Excaption not including

I have a file at /location/data.txt . In this file I have entry like :
aaa:xxx:abc.com:1857:xxx1:rel5t2:y
ifa:yyy:xyz.com:1858:yyy1:rel5t2:y
I want to access 'aaa' from my code either I mention aaa while giving the input in caps or small after running my python code it should return me aaa is the right item
But here I want to include one exception that if I give the input with -mc suffix (aaa-mc) either in small latters or in caps it should ignore the -mc.
Below is the my code and output as well which I am getting now.
def pITEMName():
global ITEMList,fITEMList
pITEMList = []
fITEMList = []
ITEMList = str(raw_input('Enter pipe separated list of ITEMS : ')).upper().strip()
items = ITEMList.split("|")
count = len(items)
print 'Total Distint ITEM Count : ', count
pipelst = [i.split('-mc')[0] for i in ITEMList.split('|')]
filepath = '/location/data.txt'
f = open(filepath, 'r')
for lns in f:
split_pipe = lns.split(':', 1)
if split_pipe[0] in pipelst:
index = pipelst.index(split_pipe[0])
pITEMList=split_pipe[0]+"|"
fITEMList.append(pITEMList)
del pipelst[index]
for lns in pipelst:
print bcolors.red + lns,' is wrong ITEM Name' + bcolors.ENDC
f.close()
When I execute above code it prompts me like :
Enter pipe separated list of ITEMS :
And if I provide the list like :
Enter pipe separated list of ITEMS : aaa-mc|ifa
it gives me the result as :
Total Distint item Count : 2
AAA-MC is wrong item Name
items Belonging to other :
Other center :
item Count From Other center = 0
items Belonging to Current Centers :
Active items in US1 :
^IFA$
Active items in US2 :
^AAA$
Ignored item Count From Current center = 0
You Have Entered itemList belonging to this center as: ^IFA$|^AAA$
Active item Count : 2
Do You Want To Continue [YES|Y|NO|N] :
As you must be see in above result aaa is coming as valid count (active item count : 2) because its available in /location/data.txt file. but also its coming as AAA-MC is wrong item name (2nd line from above result). I want '-mc or -MC' to ignore with any item present or non present in /location/data.txt file.
Please let me know what's wrong with my above code to achieving this.
The issue you're having is that your code expects the "-mc" suffix to appear in lowercase, but you're calling the upper() method on the input string, resulting in text that is all upper case. You need to change one of those so that they match (it doesn't really matter which one).
Either replace the upper() call with lower(), or replace the string "-mc" with "-MC", and your code should work better (I'm not certain I understand all of it, so there may be other issues).
The way you are constructing ITEMList is by reading in a string, capitalizing it (with upper()), and stripping all whitespace. Therefore, something like 'aaa-mc' is being converted to 'AAA-MC'. You're later splitting this uppercase string on the token '-mc', which is impossible for it to contain, so.
I'd reccommed either replacing upper() with lower() when you are reading your string in, or doing a hard replace on the types of '-mc', so instead of
i.split('-mc')[0]
try using
i.replace('-mc','').replace('-MC','')
in your list comprension.

Categories

Resources