【问题标题】:Efficient way to store and search coordinates in python在python中存储和搜索坐标的有效方法
【发布时间】:2013-03-22 22:54:41
【问题描述】:

我正在pygame中用python(2.7)编写一个简单的游戏。在这个游戏中,我必须存储 2D 坐标。这些项目的数量将从0开始,每一步增加2。它们将增加到〜6000。在每个步骤中,我必须检查其中是否有 9 个特定坐标。我尝试将它们简单地存储在 (x,y) 的列表中,但在这样的列表中搜索效率不高。

如何存储这些坐标以便在它们之间进行更高效的搜索?

我在每个步骤中尝试做的事情:

# Assuming:
myList = []
co1 = (12.3,20.2) # and so on..
valuesToCheck = [co1,co2,co3,co4,co5,co6,co7,co8,co9]

# In each step:
# Adding 2 coordinates
myList.append((x1,y1))
myList.append((x2,y2))
# Searching 9 specific coordinates among all
for coordinate in valuesToCheck:
    if coordinate in myList:
        print "Hit!"
        break
# Note that the valuesToCheck will change in each step.
del valuesToCheck[0]
valuesToCheck.append(co10)

坐标是浮点数,它们的最大值是有限的。它们从 (0.0,0.0) 开始到 (1200.0,700.0)。

我已经对此进行了搜索,但存储的值是字符串或常量。

【问题讨论】:

  • 在坐标集上你需要做的唯一搜索就是这9个特殊坐标是否在里面?这 9 个特殊坐标是否发生变化(如果没有,为什么不丢弃不匹配的 2D 点)?您还需要对您的积分进行任何其他搜索吗?
  • 正如我在代码部分添加的那样,这 9 个特殊坐标也在每一步中发生变化。不过,没有其他关于积分的搜索。
  • 在这种情况下,有这么多项目,我会保持简单并使用字典。 stackoverflow.com/questions/1938614/…
  • 元组是可散列且不可变的,因此将它们放入一个集合中检查是否存在是可行的。或者,如果您需要关联一个值,则可以使用字典。
  • 坐标总是整数吗?而且,它们是否总是受到最大值/最小值的限制? (例如,它们永远不会小于 (0,0) 或大于 (500,500))

标签: python algorithm search coordinates


【解决方案1】:

如果我理解正确,您是在向myList 添加元素,但从不删除它们。然后,您将在 myList 中测试 valuesToCheck 的每个元素以获得成员资格。

如果是这种情况,您可以通过将 myList 转换为集合而不是列表来提高性能。测试列表中的成员身份是 O(n),而测试集合中的成员身份通常是 O(1)。

您的语法将基本保持不变:

mySet = set()

# your code

# Adding 2 coordinates
mySet.add((x1,y1))
mySet.add((x2,y2))
# Searching 9 specific coordinates among all
for coordinate in valuesToCheck:
    if coordinate in mySet:
        print "Hit!"
        break
# Note that the valuesToCheck will change in each step.
del valuesToCheck[0]
valuesToCheck.append(co10)

【讨论】:

  • 使用集合会比使用字典更有效吗?还有更复杂但更有效的方法吗? (我正在寻找link K-d 树。建议@angelatlarge)
  • @SweeneyTodd- 如果您所做的只是检查成员资格,dictset 将执行基本相同的操作。关于更复杂的方法:我会首先考虑开发一些指标来衡量这部分代码在“足够好”之前需要多快。过早的优化是万恶之源 :)
【解决方案2】:

在您的列表旁边维护一个set,或者如果您没有其他用途,则完全替换该列表。成员资格检查和添加是 O(1) on average 的集合,因此与仅使用列表的 O(N^2) 相比,您的整体算法将是 O(N)。

myList = []
mySet = set()
co1 = (12,20) # and so on..
valuesToCheck = [co1,co2,co3,co4,co5,co6,co7,co8,co9]

# In each step:
# Adding 2 coordinates
myList.append((x1,y1))
myList.append((x2,y2))
mySet.add((x1, y1))
mySet.add((x2, y2))
# Searching 9 specific coordinates among all
for coordinate in valuesToCheck:
    if coordinate in mySet:
        print "Hit!"
        break
# Note that the valuesToCheck will change in each step.

del valuesToCheck[0]
valuesToCheck.append(co10)

【讨论】:

  • 使用集合会比使用字典更有效吗?还有更复杂但更有效的方法吗? (我正在寻找建议的K-d tree@angelatlarge)
  • 据我了解,集合是由后端实现的dicts,所以效率是一样的。我不知道更有效的方法,尽管我不能忽视它们的存在。
  • 为什么会是O(N^2)?列表追加不是 O(1),列表查找不是 O(n) 吗?
  • @Davos,我想我第一次误读了这个问题——我认为valuesToCheck 的大小与myList 成正比增长。因此,在for coordinate in valuesToCheck: 循环中进行列表查找将是 O(N^2)。但是再看一遍,我希望valuesToCheck 永远不会超过九个元素,因此 OP 的原始代码将是 O(N)。我仍然推荐 set 方法,给定一个恒定大小的 valuesToCheck,它总共变成 O(1)。
  • 感谢您为我澄清这一点,我认为您是对的,并会指出我错过了什么。是的,当然,我的评论与问答完全正交。在我的情况下,我将使用一个使用元组作为键的字典,因为我想存储带有坐标的数据,感谢您对复杂性的额外链接以及有关作为字典实现的集合的信息。该链接完全支持 Sets 下的声明:“请参阅 dict - 实现故意非常相似”
猜你喜欢
  • 1970-01-01
  • 2012-11-15
  • 1970-01-01
  • 2011-08-07
  • 1970-01-01
  • 2019-02-13
  • 1970-01-01
  • 2015-04-02
  • 1970-01-01
相关资源
最近更新 更多