2016-09-27 20 views
0

キネマティックオブジェクトのインスタンスを含む辞書があるとします。各キネマティックオブジェクトは、位置、速度などを持っています。プログラムの各タイムステップ更新時に、2つのアクティブオブジェクト(同じオブジェクトではないことを意識して)が参照フレーム内の同じ位置を占めるかどうかを確認します。そうした場合、これは衝突をシミュレートし、関連する2つのオブジェクトが破棄され、そのインスタンスがアクティブオブジェクト辞書から削除されます。キー(およびオブジェクト)の活性物質から除去されるが、forループの条件はこれを認識し、KeyError例外が発生します失敗:。私はdelを使用することはできません辞書から項目を削除するアプリケーション

dict actives{ 'missile' : object_c(x1, y1, z1), 
       'target' : object_c(x2, y2, z2), 
       'clutter' : object_c(x3, y3, z3), 
       ...        } 

... 

for key1 in self.actives.keys(): 
    for key2 in self.actives.keys(): 
     if not key1 == key2: 
     # Get Inertial Positions and Distance 
     Pos21 = self.actives[key2].Pos - self.actives[key1].Pos 
     distance = math.sqrt(sum(Pos21**2)) 
     # If Distance <= Critical Distance 
     if distance <= 1.0e0 
      # Remove key1 and key2 from Actives 
      # -- This is where I need help -- 

ループ条件のキーにアクセスしている間に、これらのオブジェクトをアクティブから削除するにはどうすればよいですか?

答えて

1

私はMaximilian Petersが正しい基本iを持っていたと思います無効にする必要がありますが、取り除かれるアイテムは、listではなく、setに保管して、複数のアクティブなキーに問題が生じないようにしてください。衝突検出プロセスをさらに早くするために、私はitertools.combinations()ジェネレータ関数を使用するように比較ループを変更し、ユニークなペアのオブジェクトのみをテストしました。私はまた、あなたはおそらくそれがで動作しているような文脈でそれが可能テストコードにするために足場のかなりの量を追加する必要がありました

...

from itertools import combinations 
import math 

CRITICAL_DIST = 2.0e0 

class ObjectC(object): 
    def __init__(self, x, y, z): 
     self.posn = x, y, z 
    def __repr__(self): 
     return '{}({}, {}, {})'.format(self.__class__.__name__, *self.posn) 

class Game(object): 
    def remove_collisons(self): 
     to_remove = set() 
     for key1, key2 in combinations(self.actives, 2): 
      # Calculate distance. 
      deltas = (
       (self.actives[key2].posn[0] - self.actives[key1].posn[0])**2, 
       (self.actives[key2].posn[1] - self.actives[key1].posn[1])**2, 
       (self.actives[key2].posn[2] - self.actives[key1].posn[2])**2) 
      distance = math.sqrt(sum(deltas)) 
      # Check for collision. 
      if distance <= CRITICAL_DIST: 
       to_remove |= {key1, key2} # both objects should be removed 

     if to_remove: 
      print('removing: {!r}'.format(list(to_remove))) 
      self.actives = { 
       k: v for k, v in self.actives.items() if k not in to_remove} 

x1, y1, z1 = 0, 1, 2 
x2, y2, z2 = 1, 2, 3 
x3, y3, z3 = 2, 3, 1 

actives = {'missile' : ObjectC(x1, y1, z1), 
      'target' : ObjectC(x2, y2, z2), 
      'clutter' : ObjectC(x3, y3, z3), 
      } # ... 

game = Game() 
game.actives = actives 
print('before: {}'.format(game.actives)) 
game.remove_collisons() 
print('after: {}'.format(game.actives)) 

は出力:

before: {'clutter': ObjectC(2, 3, 1), 'target': ObjectC(1, 2, 3), 'missile': ObjectC(0, 1, 2)} 
removing: ['target', 'missile'] 
after: {'clutter': ObjectC(2, 3, 1)} 
1

シンプルなソリューション、すべての要素をループした後、あなたがリストに削除し、それらを削除するキーを追加します。

dict actives{ 'missile' : object_c(x1, y1, z1), 
      'target' : object_c(x2, y2, z2), 
      'clutter' : object_c(x3, y3, z3), 
      ...        } 
to_be_removed = list() 
...

for key1 in self.actives.keys(): 
    for key2 in self.actives.keys(): 
     if not key1 == key2: 
     # Get Inertial Positions and Distance 
     Pos21 = self.actives[key2].Pos - self.actives[key1].Pos 
     distance = math.sqrt(sum(Pos21**2)) 
     # If Distance <= Critical Distance 
     if distance <= 1.0e0 
      # Remove key1 and key2 from Actives 
      # -- This is where I need help -- 


      to_be_removed.append(key1) 
      to_be_removed.append(key2) 

for remove_me in to_be_removed: 
    self.actives.pop(remove_me, None) 
+0

ことほぼ正しいと思われますが、適切な条件の下で、 'to_be_removed'リストは、2つの他のオブジェクトと同じ場所を占めるならば、' key1'の複数のインスタンスを持つことができます(すなわち、key1とkey2の間の距離は0.5、key1とkey3の間の距離0.75である)。同じキーのコピーをリストに入れると、 'pop'にKeyErrorが発生します。しかし、おそらく、辞書からポップする前に 'to_be_removed'リストを記録し、それをクリーンアップして(重複したキーを削除する)ことができます。 –

+0

@ S.Gamgee: 'default'値(この場合は' None')を指定すると、リストからキーを削除するとエラーは発生しません。 https://docs.python.org/3.5/library/stdtypes.html –

1

あなたがループしていると、

for key1 in self.actives.keys(): 

    if key1 not in self.actives: 
     continue 

    for key2 in self.actives.keys(): 

     if key2 not in self.actives: 
      continue 

     # okay, both keys are still here. go do stuff 
     if not key1 == key2: 
関連する問題