Python - 有效地检查列表中的每个项目与其他项目
Posted
技术标签:
【中文标题】Python - 有效地检查列表中的每个项目与其他项目【英文标题】:Python - Checking every item in a list against every other item efficiently 【发布时间】:2019-01-10 16:36:10 【问题描述】:我正在开发一个游戏,其中每个对象都应该检查它是否与任何其他对象发生碰撞。我有一个所有对象的列表和一个函数,它可以确定两个对象是否正在碰撞并破坏它们。我目前使用的方法效率很低。
for i in list1:
for j in list1:
if collide(i, j):
i.kill()
j.kill()
最初我在它们被杀死后从列表中删除了两个对象,但是发生了一些碰撞而没有检测到,所以我恢复到这段代码。它有效,但我想要更高效的东西。
【问题讨论】:
为什么不检查物品在移动时是否与任何东西发生碰撞? 你的对象是 pygame 中的精灵吗?如果是这样,则有更好的碰撞检测。请更具体地说明您使用的数据类型和环境。 @zacharybys 所有对象始终处于运动状态。该游戏涉及一个重力模型,其中小行星始终处于重力加速度下。 @RoryDaulton 它在 pygame 中,但是所有精灵都是圆形,因此内置的 rect 碰撞将不起作用。 【参考方案1】:首先,这是测试两次太多,还要测试一个对象是否与自身发生碰撞:
for i in list1:
for j in list1:
if collide(i, j):
i.kill()
j.kill()
这正好循环len(list1)**2
次。
一种将测试次数除以 2 的非常简单的方法(并避免针对自身进行测试):
for i,obj1 in enumerate(list1):
for j in range(i+1,len(list1)):
obj2 = list1[j]
if collide(obj1,obj2):
obj1.kill()
obj2.kill()
它利用了collide(obj1,obj2)
与collide(obj2,obj1)
相同的事实。
此时,您可能希望 break
退出内部循环,因为 obj1 现在已经死了。但这取决于你想做什么。
如果准确的碰撞测试成本高昂,您可以考虑更粗略的检查(距离、矩形边界、任何快速方法),这样您就可以丢弃彼此相距太远的项目,而无需执行“昂贵”的测试。
【讨论】:
所以这是针对所有项目检查第一项,针对除第一项之外的所有项检查第二项,针对除前两项之外的所有项检查第三项,等等? 是的,完全正确。collide(obj1,obj2)
与 collide(obj2,obj1)
相同
对,这就是它如此低效的原因。感谢您的帮助,我会标记它。
它仍然具有 O(n**2) 复杂度,但至少快两倍。
这是检查每个项目与每个项目一次的最快方法,还是更有效?以上是关于Python - 有效地检查列表中的每个项目与其他项目的主要内容,如果未能解决你的问题,请参考以下文章