如何将多个参数传递给方法' key' sorted()的?

时间:2014-03-18 15:30:12

标签: python django sorting

在网站上,我试图根据用户的相对位置对商店列表进行排序。让我解释一下。

一家商店看起来像这样:

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

3 个答案:

答案 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))