So I have created 2 classes called Invitation and Response. Then, I created a class called Event. Within the Event class, I have to create function that looks at the current list of invites and list of responses and counts how many invites have no response.
The invites and the responses both have a "name" attribute that I use in my get_pending() method.
I have a class instance called "e" that looks as follows:
e = Event("graduation",[Invitation("A",5),Invitation("B",10),Invitation("C",5),Invitation("D",7)], [Response("A",True,5),Response("B",True,6),Response("C",False,0),Response("D",True,1)])
I then print the class method get_pending:
print(e.count_pending())
Here is my code with the get_pending() method:
class Invitation:
def __init__(self, name, num_invited):
self.name = name #str
self.num_invited = num_invited #positive int
def __str__(self):
return ("Invitation('%s', %i)" % (self.name, self.num_invited))
def __repr__(self):
return str(self)
def __eq__(self, other):
if self.name == other.name and self.num_invited == other.num_invited:
return True
def __lt__(self, other):
if self.name < other.name:
return True
elif self.name == other.name:
if self.num_invited < other.num_invited:
return True
class Response:
def __init__(self, name, ans, num_attending):
self.name = name #str
self.ans = ans #bool - T/F
self.num_attending = num_attending #zero or more people
def __str__(self):
return ("Response('%s', %r, %i)" % (self.name, self.ans, self.num_attending))
def __repr__(self):
return str(self)
def __eq__(self, other):
if self.name == other.name and self.ans == other.ans and self.num_attending == other.num_attending:
return True
def __lt__(self, other):
if self.name < other.name:
return True
elif self.name == other.name:
if self.ans < other.ans:
return True
elif self.ans == other.ans:
if self.num_attending < other.num_attending:
return True
class Event:
def __init__(self, title, invites=None, responses=None):
self.title = title #str
self.invites = invites #list
self.responses = responses #list
if self.invites == None:
self.invites = []
if self.responses == None:
self.responses = []
self.invites.sort()
self.responses.sort()
def __str__(self):
return ("""Event('%s', %r, %r)""" % (self.title, self.invites, self.responses))
def __repr__(self):
return str(self)
def __eq__(self, other):
if self.title == other.title and self.invites == other.invites and self.responses == other.responses:
return True
def count_pending(self):
num_pending = 0
lst_noresp = self.invites[:]
for invi in lst_noresp:
if (any(invi.name == resp.name for resp in self.responses)) == True:
lst_noresp.remove(invi)
for invi in lst_noresp:
num_pending += invi.num_invited
return num_pending
e = Event("graduation",[Invitation("A",5),Invitation("B",10),Invitation("C",5),Invitation("D",7)], [Response("A",True,5),Response("B",True,6),Response("C",False,0),Response("D",True,1)])
print(e.count_pending())
My error is that the count_pending() method is only removing some (Invite with name 'A' and Invite with name 'C') objects from the invite list even though all invites have a corresponding response. Why isn't the invi.name == resp.name comparison working properly? Or, is that even the issue?
You have the classic problem of mutating a list
while iterating it here:
for invi in lst_noresp: # Iterating
if (any(invi.name == resp.name for resp in self.responses)) == True:
lst_noresp.remove(invi) # Mutating
While there is no documented behavior for it, in practice, this causes the loop to skip the value following each removed element (the iterator stores the current index, and the remove
shifts the following elements down, so when you get the next element, you've bypassed the element that was shifted into the space occupied by the removed element), so you're not even checking half your values. Iterate over self.invites
, and mutate lst_noresp
, and the problem should disappear.
Alternatively, construct a new list
and avoid O(n**2)
performance:
lst_noresp = [invi for invi in self.invites
if not any(invi.name == resp.name for resp in self.responses)]
which avoids slow removals from the middle of a list
in favor of filtering during construction of a new list
( O(n)
work).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.