Jes*_*eTG 3 python iteration comparison set
所以我正在写一个游戏.以下是碰撞检测的工作原理; 有一个不可见的网格,并且根据它们的位置在单元格中添加和删除对象(或者更确切地说,它们的引用).碰撞比较仅在同一单元格中的对象之间进行.
引用存储在set每个单元所拥有的Python 中.它必须是一套.当检测到碰撞时,它存储在Collision具有三个属性的对象中; 碰撞的两个物体和碰撞发生的时间.当考虑所有碰撞时,它们按时间排序,然后进行处理.
这是各个单元用于检查冲突的循环;
#grid.collisions is a list of recorded collisions, and self.objects is the set
#of objects currently in this cell.
for i in self.objects:
for j in self.objects:
if id(i) != id(j) and pygame.sprite.collide_rect(i, j):
grid.collisions.append(Collision(i, j))
Run Code Online (Sandbox Code Playgroud)
问题是,这比较了两个相同的两个对象; 如果我们有一套{1, 2, 3, 4},我们会比较(1, 2) 和 (2, 1).不仅如此,这些重复的比较被添加到总冲突列表中,从而打破了整个系统!
我知道我不能索引集合,这意味着我不能做像for j in range(i, len(self.objects))在哪里i,j都是整数. 如何解决此限制以确保同一组中的两个对象不进行两次比较? 我无法删除这些集合中的对象; 只有在对象离开网格单元格时才会删除它们.
由于每帧都会处理这些冲突,我宁愿避免创建新对象(真正的代码不像Collisions示例那样创建新的,我只是简化它以便于阅读).我可以删除重复的比较,但是将每次碰撞与其他碰撞进行比较会产生很多开销.
如果你的目标只是比较集合的所有独特组合,你可以使用 itertools.combinations
from itertools import combinations
for i, j in combinations(self.objects, 2):
if pygame.sprite.collide_rect(i, j):
grid.collisions.append(Collision(i, j))
Run Code Online (Sandbox Code Playgroud)
例:
aSet = set([1,2,3,4])
list(combinations(aSet, 2))
# [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
Run Code Online (Sandbox Code Playgroud)
combinations 与管理多个索引和临时列表相比,它生成了一个非常高效的生成器