在网站上,我试图根据用户的相对位置对商店列表进行排序。让我解释一下。
一家商店看起来像这样:
class Shop(models.Model):
latitude = models.DecimalField(max_digits=9, decimal_places=6)
longitude = models.DecimalField(max_digits=9, decimal_places=6)
我在会话中获得了用户的位置。
request.session['user_latitude']
request.session['user_longitude']
所以现在我得到了一个商店列表,我想对它们进行排序。所以我尝试了这个:
def distance_of_the_shop(shop):
# compute the distance between the shop and the user and return it
return computed_distance
sorted(shop_list, key=distance_of_the_shop)
问题很简单,如何将多个参数传递给方法distance_of_the_shop
?
答案 0 :(得分:13)
将呼叫包裹在lambda中:
ulong, ulat = request.session['user_latitude'], request.session['user_longitude']
sorted(shop_list, key=lambda shop: distance_of_the_shop(shop, ulong, ulat))
并向distance_of_the_shop()
函数添加两个参数以接收经度和纬度。
sorted()
函数为key
中的每个值调用shop_list
,但没有任何内容表示调用者本身不能调用其他函数。 lambda
是创建新包装函数的最简单方法。
您还可以使用functools.partial()
object,前提是经度和纬度值可以作为关键字参数传递,或者将这两个值作为前两个位置参数接受。将它们作为关键字参数处理可能是最好的,即使它们被赋予位置(没有默认值),您也可以在partial()
中将它们的名称用作关键字参数。
假设定义是:
def distance_of_the_shop(shop, long, lat):
# ...
然后使用
sorted(shop_list, key=partial(distance_of_the_shop, long=ulong, lat=ulat))
和sorted()
会将每个shop
传递给partial()
,后者又调用distance_of_the_shop(shop, long=ulong, lat=ulat)
答案 1 :(得分:1)
您的问题很难理解,因为您从未定义distance
函数,而您提供的函数distance_of_the_shop
实际上只需要一个参数。
如果我理解正确,您希望distance_of_the_shop
接收当前用户和正在比较的商店。为此,请使用lambda
:
shop_list.sort(key=lambda shop: distance_of_the_shop(user, shop))
另请注意,如果不将其值分配给某个变量或容器,则调用sorted
是没有意义的。如果要对列表进行就地排序,请使用其sort
方法,如上所示。
答案 2 :(得分:1)
首先,我们需要一个距离函数(这个计算大圆距离):
from math import radians, cos, sin, asin, sqrt
def haversine(lon1, lat1, lon2, lat2):
"""
Calculate the great circle distance between two points
on the earth (specified in decimal degrees)
"""
# from stackoverflow.com/questions/4913349/haversine-formula-in-python-bearing-and-distance-between-two-gps-points#4913653
# convert decimal degrees to radians
lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
# haversine formula
dlon = lon2 - lon1
dlat = lat2 - lat1
a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
c = 2 * asin(sqrt(a))
# 6367 km is the radius of the Earth
km = 6367 * c
return km
然后我们为每个用户定义一个距离函数:
def dist_from_user(user):
# This is kind of funky, because the `user` parameter is
# not used, we simply assume that user is the current session-holder.
# It would make more sense if we actually had more than
# one user to choose between.
lat = float(request.session['user_latitude'])
lon = float(request.session['user_longitude'])
def shop_dist(shop):
s_lat = float(shop.latitude)
s_lon = float(shop.longitude)
return haversine(lon, lat, s_lon, s_lat)
return shop_dist
并将其称为
shop_list.sort(key=dist_from_user(user))