从字典中删除项目的应用

2024-05-23 19:03:04 发布

您现在位置:Python中文网/ 问答频道 /正文

假设我有一个包含运动学对象实例的字典。每个运动学对象都有一个位置、速度等。对于程序的每个时间步更新,我要检查两个活动对象(不是同一个对象,请注意)是否在参考帧中占据相同的位置。如果它们这样做了,这将模拟一个碰撞,所涉及的两个对象将被销毁,它们的实例将从活动对象字典中删除

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

我不能使用del:键(和对象)将从活动中删除,但是for循环的条件无法识别这一点,并且将遇到一个键错误。在访问循环条件的键时,如何从活动中删除这些对象


Tags: and对象实例inselfforif字典
3条回答

我认为Maximilian Peters的基本思想是正确的,但是要删除的项应该保存在set而不是list中,以避免活动键多次出现在其中的问题。为了进一步加快碰撞检测过程,我将比较循环更改为使用^{}生成器函数,以便只测试唯一的对象对

我还必须添加大量的脚手架,使它有可能在一个上下文中测试代码,就像你可能有它运行在

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

在循环时,可以再次检查密钥是否仍然存在:

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:

简单的解决方案是,将要删除的键添加到列表中,然后在遍历所有元素后删除它们:

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)

相关问题 更多 >