算法找到附近的朋友?

时间:2011-01-07 06:18:28

标签: python algorithm

我有一个python程序坐在服务器端管理用户位置信息,每个朋友有一对(经度,纬度),给定一个(经度,纬度)点,我怎么能找到附近的(比如在5KM以内)的朋友有效?

我有10K用户在线...

感谢。 滨

4 个答案:

答案 0 :(得分:7)

新答案:

我会将lat和long存储在单独的列中。在它们上放置索引。然后,当您想要找到特定用户的附近朋友时,只需执行类似

的操作
select field1, field1, ..., fieldn from users 
where 
    user_lat > this_lat - phi and user_lat < this_lat + phi
    and
    user_lon > this_lon - omega and user_lon < this_lon + omega

其中phiomega是与您所需距离对应的纬度和经度。这将取决于你在地球上的位置,但有确定的方程式来计算它。您的数据库也可能为您进行这些计算。


老答案。

我会看quadtreeskd-trees

Kd-trees将是这里的规范解决方案,我相信。

答案 1 :(得分:2)

一种简单的方法是沿着长度排序点,然后,当查找朋友时,找到可能匹配的最小和最大长度。对列表进行排序是O(n log n),查找朋友是线性的,但仅适用于长度范围内的朋友。以下是平面2D曲面上所有点的情况示例:

# friends is the sorted list of (x, y) tuples, (px, py) is my location
def get_near(friends, px, py, maxdist):
    i1 = bisect.bisect_left(friends, (px - maxdist, py))
    i2 = bisect.bisect_right(friends, (px + maxdist, py))
    return [(x, y) for (x, y) in friends[i1:i2] if math.hypot(px - x, py - y) < maxdist]

对于经度/纬度情况,您必须使用另一个函数来测试距离而不是欧氏距离(math.hypot)。

答案 2 :(得分:2)

制作一个词典{graticule:[users]}(“经纬网”是1度纬度x经度1度的块;所以你基本上只能对值进行舍入)。要查找附近的用户,首先从相同和相邻的经纬网获取用户(因为目标可能在边缘附近),然后使用基本边界框测试过滤它们(即,对于某人内部可能的最小经度/纬度是多少?所需的半径),然后做一个详细的测试(如果你需要准确性,那么你需要更复杂的数学而不仅仅是毕达哥拉斯)。

答案 3 :(得分:1)

http://www.movable-type.co.uk/scripts/latlong.html就效率而言,唯一真正想到的就是在条目进入数据库时​​预先计算距离,即有另一个表存储一对位置以及距离,对于在添加时添加的每个位置,您需要计算它与系统中其他每个点的距离的成本,但随后在此表上查找可以快速解析一定距离内的位置。

Aaronasterling的答案似乎是我自己想要思考但却不知道存在的:)所以它可能是一个更好的解决方案,但我相信你会在搜索时使用该算法产生一些开销(虽然可能很小,因为一般来说,只要合理平衡通常是一个非常快速的过程,我会花一些时间来理解树的组成方式,这对我来说仍然是一个新概念)。