How to pass multiple arguments to the method 'key' of sorted()? How to pass multiple arguments to the method 'key' of sorted()? django django

How to pass multiple arguments to the method 'key' of sorted()?


Just wrap the call in a lambda:

ulong, ulat = request.session['user_latitude'], request.session['user_longitude']sorted(shop_list, key=lambda shop: distance_of_the_shop(shop, ulong, ulat))

and add two more arguments to the distance_of_the_shop() function to receive the longitude and latitude.

The sorted() function calls the key for each value in shop_list, but nothing says the callable cannot itself call other functions. A lambda is the easiest way to create a new wrapper function that does just that.

You could also use a functools.partial() object, provided the longitude and latitude values can be passed in as keyword arguments, or accepts those two values as the first two positional arguments. Treating them as keyword arguments is probably best, even if they are given a position (no default value), you can use their names as keyword arguments in the partial().

Assuming the definition is:

def distance_of_the_shop(shop, long, lat):    # ...

then use

sorted(shop_list, key=partial(distance_of_the_shop, long=ulong, lat=ulat))

and sorted() will pass each shop to the partial(), which in turn calls distance_of_the_shop(shop, long=ulong, lat=ulat)


Your question is hard to comprehend because you never define a distance function, and the function you do provide, distance_of_the_shop, actually takes a single argument.

If I understand correctly, you would like distance_of_the_shop to receive the current user and the shop being compared. To achieve that, use a lambda:

shop_list.sort(key=lambda shop: distance_of_the_shop(user, shop))

Also note that it doesn't make sense to call sorted without assigning its value to some variable or container. If you want to sort a list in-place, use its sort method, as shown above.


First, we need a distance function (this one calculates great-circle distances):

from math import radians, cos, sin, asin, sqrtdef 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

then we define a distance-function per user:

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

and call it like

shop_list.sort(key=dist_from_user(user))