So I am rather new to programming and just recently started with Classes and we are supposed to make a phonebook that can be loaded in seperate text files.
I however keep running into the problem in this section that when I get into the for-loop. It hits a brick wall on
if storage[2] == permaStorage[i].number:
And tells me "IndexError: list index out of range". I am almost certain it is due to permaStorage starts out empty, but even when I attempt to fill it with temporary instances of Phonebook it tells me it out of range. The main reason it is there is to check if a phone number already exists within the permaStorage.
Anyone got a good tip on how to solve this or work around it?
(Sorry if the text is badly written. Just joined this site and not sure on the style)
class Phonebook():
def __init__(self):
self.name = ''
self.number = ''
def Add(name1, number1):
y = Phonebook()
y.name = name1
y.number = number1
return y
def Main():
permaStorage = []
while True:
print " add name number\n lookup name\n alias name newname\n change name number\n save filename\n load filename\n quit\n"
choices = raw_input ("What would you like to do?: ")
storage = choices.split(" ")
if storage[0] == "add":
for i in range(0, len(permaStorage)+1):
if storage[2] == permaStorage[i].number:
print "This number already exists. No two people can have the same phonenumber!\n"
break
if i == len(permaStorage):
print "hej"
try:
tempbox = Add(storage[1], storage[2])
permaStorage.append(tempbox)
except:
raw_input ("Remember to write name and phonenumber! Press any key to continue \n")
I think problem is that permaStorage is empty list and then u try to:
for i in range(0, len(permaStorage)+1):
if storage[2] == permaStorage[i].number:
will cause an error because permaStorage has 0 items but u trying to get first (i=0, permaStorage[0]) item.
I think you should replace second if clause with first one:
for i in range(0, len(permaStorage)+1):
if i == len(permaStorage):
print "hej"
try:
tempbox = Add(storage[1], storage[2])
permaStorage.append(tempbox)
if storage[2] == permaStorage[i].number:
print "This number already exists. No two people can have the same phonenumber!\n"
break
So in this case if perStorage is blank you will append some value and next if clause will be ok.
Indexing starts at zero in python. Hence, a list of length 5 has the last element index as 4 starting from 0. Change range to range(0, len(permastorage))
You should iterate upto the last element of the list, not beyond.
Try -
for i in range(0, len(permaStorage)):
The list of numbers produced in range() is from the start, but not including the end, so range(3) == [0, 1, 2].
So if your list x has length 10, range(0, len(x)) will give you 0 through 9, which is the correct indices of the elements of your list.
Adding 1 to len(x) will produce the range 0 through 10, and when you try to access x[10], it will fail.
Related
doc = "unsorted.txt"
out_fil = "H:\Grade 11\Intro to Computer Science\sorted.txt" # Used in the Windows variation of the program
out_file = "/Applications/Banter" # Used in the Mac variation of the program
import time
def main():
order = False
blank = []
passcount = 0
starttime = time.time()
numlist = CreateList(doc)
while not order:
passcount = passcount + 1
switch = False
switchcount = 0
print "1" # These are test prints to I used to find problems
for x in range (len(numlist)):
print "2" # These are test prints to I used to find problems
if numlist[x] > numlist[x+1]:
temp = numlist[x+1]
numlist[x+1] = numlist[x]
numlist[x] = temp
switchcount = switchcount + 1
switch = True
print "9" # These are test prints to I used to find problems
elif switch == 0:
order = True
CreateFile(numlist)
endtime = time.time()
print "This list required",endtime-starttime,"seconds to sort."
print "This list required",switchcount,"switches to sort."
print "This list required",passcount,"passes to sort."
def CreateList(doc):
sort = open(doc,"r")
numlist = sort.readlines()
sort.close()
for x in range (len(numlist)):
numlist[x] = int(numlist[x].strip())
return numlist
def CreateFile(numlist):
sort = open(doc,"w")
sort.write(str(numlist)+"\n")
sort.close()
return numlist
def List(numlist):
print numlist
main()
The main purpose of my program is to sort a list of integers from a file in order using the bubble sort method, and then put that list into a new file. I'm also detailing the amount of time it takes to perform this as well as the number of passes and switches within the program that it took to sort it completely.
Now, the problem I'm having is that the list index falls out of range because it's comparing x and x+1 of my numlist. But, I need to compare x+1 in order to sort the two integers beside each others within the list. Is there any way I can fix the program so that it'll compare all the integers in the list and not try to compare the space that isn't in the list because of the x+1?
You could make your loop in this way:
for x in range ( len(numlist) -1 ):
Though stackoverflow is a great resource for answers, giving them up for homework assignments feels like cheating. I'll meet you half way: Make your loop run for one less iteration.
What I am trying to do is write a program that opens a .txt file with movie reviews where the rating is a number from 0-4 followed by a short review of the movie. The program then prompts the user to open a second text file with words that will be matched against the reviews and given a number value based on the review.
For example, with these two sample reviews how they would appear in the .txt file:
4 A comedy-drama of nearly epic proportions rooted in a sincere performance by the title character undergoing midlife crisis . 2 Massoud 's story is an epic , but also a tragedy , the record of a tenacious , humane fighter who was also the prisoner -LRB- and ultimately the victim -RRB- of history .
So, if I were looking for the word "epic", it would increment the count for that word by 2 (which I already have figured out) since it appears twice, and then append the values 4 and 2 to a list of ratings for that word.
How do I append those ints to a list or dictionary related to that word? Keep in mind that I need to create a new list or dicitonary key for every word in a list of words.
Please and thank you. And sorry if this was poorly worded, programming isn't my forte.
All of my code:
def menu_validate(prompt, min_val, max_val):
""" produces a prompt, gets input, validates the input and returns a value. """
while True:
try:
menu = int(input(prompt))
if menu >= min_val and menu <= max_val:
return menu
break
elif menu.lower == "quit" or menu.lower == "q":
quit()
print("You must enter a number value from {} to {}.".format(min_val, max_val))
except ValueError:
print("You must enter a number value from {} to {}.".format(min_val, max_val))
def open_file(prompt):
""" opens a file """
while True:
try:
file_name = str(input(prompt))
if ".txt" in file_name:
input_file = open(file_name, 'r')
return input_file
else:
input_file = open(file_name+".txt", 'r')
return input_file
except FileNotFoundError:
print("You must enter a valid file name. Make sure the file you would like to open is in this programs root folder.")
def make_list(file):
lst = []
for line in file:
lst2 = line.split(' ')
del lst2[-1]
lst.append(lst2)
return lst
def rating_list(lst):
'''iterates through a list of lists and appends the first value in each list to a second list'''
rating_list = []
for list in lst:
rating_list.append(list[0])
return rating_list
def word_cnt(lst, word : str):
cnt = 0
for list in lst:
for word in list:
cnt += 1
return cnt
def words_list(file):
lst = []
for word in file:
lst.append(word)
return lst
##def sort(words, occurrences, avg_scores, std_dev):
## '''sorts and prints the output'''
## menu = menu_validate("You must choose one of the valid choices of 1, 2, 3, 4 \n Sort Options\n 1. Sort by Avg Ascending\n 2. Sort by Avg Descending\n 3. Sort by Std Deviation Ascending\n 4. Sort by Std Deviation Descending", 1, 4)
## print ("{}{}{}{}\n{}".format("Word", "Occurence", "Avg. Score", "Std. Dev.", "="*51))
## if menu == 1:
## for i in range (len(word_list)):
## print ("{}{}{}{}".format(cnt_list.sorted[i],)
def make_odict(lst1, lst2):
'''makes an ordered dictionary of keys/values from 2 lists of equal length'''
dic = OrderedDict()
for i in range (len(word_list)):
dic[lst2[i]] = lst2[i]
return dic
cnt_list = []
while True:
menu = menu_validate("1. Get sentiment for all words in a file? \nQ. Quit \n", 1, 1)
if menu == True:
ratings_file = open("sample.txt")
ratings_list = make_list(ratings_file)
word_file = open_file("Enter the name of the file with words to score \n")
word_list = words_list(word_file)
for word in word_list:
cnt = word_cnt(ratings_list, word)
cnt_list.append(word_cnt(ratings_list, word))
Sorry, I know it's messy and very incomplete.
I think you mean:
import collections
counts = collections.defaultdict(int)
word = 'epic'
counts[word] += 1
Obviously, you can do more with word than I have, but you aren't showing us any code, so ...
EDIT
Okay, looking at your code, I'd suggest you make the separation between rating and text explicit. Take this:
def make_list(file):
lst = []
for line in file:
lst2 = line.split(' ')
del lst2[-1]
lst.append(lst2)
return lst
And convert it to this:
def parse_ratings(file):
"""
Given a file of lines, each with a numeric rating at the start,
parse the lines into score/text tuples, one per line. Return the
list of parsed tuples.
"""
ratings = []
for line in file:
text = line.strip().split()
if text:
score = text[0]
ratings.append((score,text[1:]))
return ratings
Then you can compute both values together:
def match_reviews(word, ratings):
cnt = 0
scores = []
for score,text in ratings:
n = text.count(word)
if n:
cnt += n
scores.append(score)
return (cnt, scores)
I need to get user input to generate a list of 8 numbers, but when they input a number that is already in the list print and error . Without using the in function to determine if its in the list. Here's what I have so far.
def main():
myList = range(9)
a= True
for i in myList:
while a == True:
usrNum = int(input("Please enter a number: "))
if usrNum != myList[i]:
myList.append(usrNum)
print(i)
main()
Error for above code,
Scripts/untitled4.py", line 18, in main
myList.append(usrNum)
AttributeError: 'range' object has no attribute 'append'
The issue seems to be your way of generating myList. If you generate it with myList = [range(9)] you'll get:
[[0, 1, 2, 3, 4, 5, 6, 7, 8]]
Try using simply:
myList = range(9)
Also, you need to change myList.append[usrNum] with myList.append(usrNum) or you'll get a:
TypeError: 'builtin_function_or_method' object has no attribute '__getitem__'
You could also use wim's suggestion instead of the != operator:
if myList.__contains__(usrNum):
myList.append(usrNum)
There are two ways you can go about this:
Loop through the list to check each element.
The in operator is effectively doing:
for each value in the list:
if the value is what you're looking for
return True
if you reach the end of the list:
return False
If you can add that check into your code, you'll have your problem solved.
Use an alternate way of tracking which elements have been added
Options include a dict, or bits of an int.
For example, create checks = {}. When you add an value to the list, set checks[usrNum] = True. Then checks.get(usrNum, False) will return a boolean indicating whether the number already exists. You can simplify that with a collections.DefaultDict, but I suspect that may be more advanced than you're ready for.
The first is probably the result your instructor is after, so I'll give you a simple version to work with and massage to fit your needs.
myList = []
while True:
usrNum = int(input())
found = False
for v in myList:
if usrNum == v:
found = True
if not found:
myList.append(usrNum)
else:
#number was already in the list, panic!
Most instructors will be more impressed, and hence award better grades, if you can figure out how to do something like method 2, however.
You could do something like this, modify as needed (not sure when/if you want to break when the user enters a number that is already in the list, etc.)
This prompts for user input until they enter an item that already exists in the list, then it prints a message to the user, and stops execution.
def main():
mylist = range(9)
while True:
usrNum = int(input("Please enter a number: "))
if existsinlist(mylist, usrNum):
print("{} is already in the list {}".format(usrNum, mylist))
break
else:
mylist.append(usrNum)
def existsinlist(lst, itm):
for i in lst:
if itm == i:
return True
return False
Perhaps the point of this homework assignment is to help you understand how an operator like in is more efficient to read (and write, and compile) than the explicit loop that I used in the existsinlist function.
Not sure if list-comperehension would be allowable in this case, but you also could've done something like this, without relying on the existsinlist helper function:
def main():
mylist = range(9)
while True:
usrNum = int(input("Please enter a number: "))
if [i for i in mylist if i == usrNum]:
print("{} is already in the list {}".format(usrNum, mylist))
break
else:
mylist.append(usrNum)
In this case, the result of the list-comprehension can be evaluated for truthiness:
An empty list like [] results if no matching value exists, and this will be considered False
A non-empty list will result if at least one matching value exists, and this will be considered True
Yet another option which short-circuits and may be preferable:
if any(usrNum == i for i in mylist)
For example I have a list with a month and the month number, I want to add in another value in [0][1], [1][1],[2][1] every time I input a new value. I'm thinking of the append function however I'm unsure how to re-code that to make that value to input into the the next list along in the list.
list = [[['Jan'],1], [['Feb'],2],[['Mar'],3]]
def month():
global list
count = 0
while value_count < 3:
value = int(input("Enter a value: "))
if value in range(101):
list[0][1].append(value)
count += 1
else:
print('Try Again.')
month()
I want to result with something like:
list = [[['Jan'],1,54], [['Feb'],2,65],[['Mar'],3,62]]
Where 54, 65 and 62 are random numbers a user has entered.
Please see the comments in the code
# list is a function used by python to create lists,
# do not use builtins' names for your variables
my_list = [[['Jan'],1], [['Feb'],2],[['Mar'],3]]
def month():
# print("Don't use globals!\n"*100)
# you can pass arguments to a function, like in "def mont(my_list)"
global my_list
# cycling on a numerical index is complicated, use this syntax
# instead, meaning "use, in turn, the same name to refer to each
# element of the list"
for element in my_list:
value = int(input("Enter a value: "))
# if value in range(101):
if 1: # always true, the test doesn't work as you expect
element.append(value)
else:
print('Try Again.')
month()
print my_list
you can write the input loop like this
value = 101
while not (0<=value<101):
value = int(input(...)
element.append(value)
this way you'll miss the alternative prompt but it's good enough.
I'm trying to implement a function to find occurrences in a list, here's my code:
def all_numbers():
num_list = []
c.execute("SELECT * FROM myTable")
for row in c:
num_list.append(row[1])
return num_list
def compare_results():
look_up_num = raw_input("Lucky number: ")
occurrences = [i for i, x in enumerate(all_numbers()) if x == look_up_num]
return occurrences
I keep getting an empty list instead of the ocurrences even when I enter a number that is on the mentioned list.
Your code does the following:
It fetches everything from the database. Each row is a sequence.
Then, it takes all these results and adds them to a list.
It returns this list.
Next, your code goes through each item list (remember, its a sequence, like a tuple) and fetches the item and its index (this is what enumerate does).
Next, you attempt to compare the sequence with a string, and if it matches, return it as part of a list.
At #5, the script fails because you are comparing a tuple to a string. Here is a simplified example of what you are doing:
>>> def all_numbers():
... return [(1,5), (2,6)]
...
>>> lucky_number = 5
>>> for i, x in enumerate(all_numbers()):
... print('{} {}'.format(i, x))
... if x == lucky_number:
... print 'Found it!'
...
0 (1, 5)
1 (2, 6)
As you can see, at each loop, your x is the tuple, and it will never equal 5; even though actually the row exists.
You can have the database do your dirty work for you, by returning only the number of rows that match your lucky number:
def get_number_count(lucky_number):
""" Returns the number of times the lucky_number
appears in the database """
c.execute('SELECT COUNT(*) FROM myTable WHERE number_column = %s', (lucky_number,))
result = c.fetchone()
return result[0]
def get_input_number():
""" Get the number to be searched in the database """
lookup_num = raw_input('Lucky number: ')
return get_number_count(lookup_num)
raw_input is returning a string. Try converting it to a number.
occurrences = [i for i, x in enumerate(all_numbers()) if x == int(look_up_num)]