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 - 有效地检查列表中的每个项目与其他项目的主要内容,如果未能解决你的问题,请参考以下文章

布尔列表检查列表中的每个项目是不是为假

通过放置一个列表中的每个第 n 个项目和另一个列表中的其他项目来合并 Python 中的列表?

有效地检查一个元素是不是在列表中至少出现 n 次

如何有效地找到从每个值到下一个较低/较高值的距离?

有效地找到距另一点最近的点

有效地检查 Python / numpy / pandas 中的任意对象是不是为 NaN?