2017-12-08 14 views
0

私はInvitationとResponseという2つのクラスを作成しました。次に、Eventというクラスを作成しました。 Eventクラス内では、現在の招待リストと返答リストを調べ、応答がない招待の数を数える関数を作成する必要があります。このインスタンスがオブジェクトのリストから削除されないのはなぜですか?

招待状と回答には、どちらもget_pending()メソッドで使用する「名前」属性があります。

私は以下のように見える "E" と呼ばれるクラスのインスタンスを持っている:

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)]) 

私は、クラスメソッドget_pendingを印刷:ここ

print(e.count_pending()) 

はget_pending()メソッドを持つ私のコードです:

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()) 

私のエラーは、count_pending()メソッドは、すべての招待に対応する応答があっても、招待リストからのオブジェクト(名前「A」と名前「C」で招待する」)でオブジェクトを招待します。 invi.name == resp.nameの比較が正しく機能しないのはなぜですか?それとも問題なのでしょうか?

+0

'if'が正しく動作するかどうかを確認するために、' lst_noresp.remove(invi) 'の直前または直後の' print(invi) 'のデバッグのためのいくつかの' print'が役に立ちます。 –

+0

問題が公開されている場合は、その旨を反映するようにコードを更新し、ここに返信します。 – ruckarucka

+0

@MichaelButscherだから私は、 "if(any(invi.name == resp.name for self.responses))== True:"という行は、2番目と4番目の招待状のジェネレータ出口になりますが、 1回目と3回目の招待ではない – ruckarucka

答えて

1

あなたがここでそれを反復しながら、listを変異の古典的な問題があります。それには文書化された動作はありませんが

for invi in lst_noresp: # Iterating 
     if (any(invi.name == resp.name for resp in self.responses)) == True: 
      lst_noresp.remove(invi) # Mutating 

は、実際には、これは各削除要素以下の値をスキップするループを引き起こし(イテレータは現在のインデックスを格納し、removeは次の要素を下にシフトします。したがって、次の要素を取得すると、削除された要素が占める領域に移動した要素はバイパスされます)。あなたの価値の半分をチェックする。 self.invitesを反復し、lst_norespを変更してください。この問題は消えます。

また、新しいlistを構築し、O(n**2)パフォーマンス避ける:

lst_noresp = [invi for invi in self.invites 
        if not any(invi.name == resp.name for resp in self.responses)] 

新しいlistO(n)仕事)の建設中のフィルタリングの賛成でlistの途中から遅い削除を回避することができます。

+0

ありがとうございます! (私がよく慣れ親しんでいる)この問題を解決するもう一つの方法は、既に応答に存在する招待状を削除するのではなく、単純に新しいリストに応答しない招待状を追加してそのリストを反復することができますか? – ruckarucka

+0

@ruckarucka:Heh。私はあなたがコメントしたときにそのアプローチを追加していました。そうですね、一般的には単純で効率的です。サンプルコードを参照してください。 – ShadowRanger

+0

はい、私は完全に同意します、更新されたコードありがとうございます。 – ruckarucka

関連する問題