【发布时间】:2011-03-03 20:53:10
【问题描述】:
我有一个非常简单的 python 例程,其中涉及循环遍历大约 20,000 个纬度、经度坐标的列表并计算每个点到参考点的距离。
def compute_nearest_points( lat, lon, nPoints=5 ):
"""Find the nearest N points, given the input coordinates."""
points = session.query(PointIndex).all()
oldNearest = []
newNearest = []
for n in xrange(nPoints):
oldNearest.append(PointDistance(None,None,None,99999.0,99999.0))
newNearest.append(obj2)
#This is almost certainly an inappropriate use of deepcopy
# but how SHOULD I be doing this?!?!
for point in points:
distance = compute_spherical_law_of_cosines( lat, lon, point.avg_lat, point.avg_lon )
k = 0
for p in oldNearest:
if distance < p.distance:
newNearest[k] = PointDistance(
point.point, point.kana, point.english, point.avg_lat, point.avg_lon, distance=distance
)
break
else:
newNearest[k] = deepcopy(oldNearest[k])
k += 1
for j in range(k,nPoints-1):
newNearest[j+1] = deepcopy(oldNearest[j])
oldNearest = deepcopy(newNearest)
#We're done, now print the result
for point in oldNearest:
print point.station, point.english, point.distance
return
我最初是用 C 语言编写的,使用完全相同的方法,它在那里运行良好,并且对于 nPoints
我第一次移植它时没有使用现在使用该方法的 deepcopy 语句,这导致结果“奇怪”或部分不正确,因为某些点只是被复制为引用(我猜?我想? ) -- 但它仍然几乎和 C 版本一样快。
现在添加 deepcopy 调用后,例程可以正常工作,但会导致极大的性能损失,现在需要几秒钟才能完成相同的工作。
这似乎是一个很常见的工作,但我显然不是以 Python 的方式来做的。我应该怎么做才能得到正确的结果,但不必在任何地方都包含 deepcopy?
编辑:
我找到了一个更简单、更快的解决方案,
def compute_nearest_points2( lat, lon, nPoints=5 ):
"""Find the nearest N points, given the input coordinates."""
points = session.query(PointIndex).all()
nearest = []
for point in points:
distance = compute_spherical_law_of_cosines( lat, lon, point.avg_lat, point.avg_lon )
nearest.append(
PointDistance(
point.point, point.kana, point.english, point.avg_lat, point.avg_lon, distance=distance
)
)
nearest_points = sorted(nearest, key=lambda point: point.distance)[:nPoints]
for item in nearest_points:
print item.point, item.english, item.distance
return
所以基本上我只是制作输入的完整副本并附加一个新值 - 与参考点的距离。然后我只是对结果列表应用“排序”,指定排序键应该是 PointDistance 对象的距离属性。
这比使用 deepcopy 快得多,尽管我承认我真的不明白为什么。我猜这要归功于高效的 C 实现 python 的“排序”?
【问题讨论】:
-
PointDistance类的外观如何?如果您使PointDistance类成为一个简单的类,它只引用原始点及其距离(即它实际上是一个包含两个元素的元组),您不需要使用deepcopy因为点不会改变在算法期间,距离是一个简单的数字。 -
@Tamás 是的,它基本上只是一本字典。但是,在第一个示例中,如果没有 deepcopy,这绝对不能正常工作。如果我完全取消课程并改用字典,也许它会起作用?老实说,我只是对参考模型没有足够清晰的了解,无法知道在这些情况下会发生什么。也许您可以详细说明或指出有关该主题的其他资源或帖子?