I would like to know how I can implement advanced sorting functions that I can pass in as tuple element to the key argument of the python 'sorted' function.
Here is an example depicting what I would like to do:
class Book:
def __init__(self, name, author, language, cost):
self.name = name
self.author = author
self.language=language
self.cost = cost
bookList = [list of books]
firstLanguage = "Armenian"
possibleLanguages = ["English", "Spanish", "Armenian", "French", "Chinese", "Swahili"]
possibleLanguages.remove("Armenian")
sortedBookList = sorted(bookList, key=(sortByName,
sortByFirstLanguage(firstLanguage), sortByLanguages(possibleLanguages) ))
Basically I would like to implement the 'sortByFirstLanguage' and 'sortByLanguages' functions described above so that I can pass them to the python 'sorted' function as the tuple items of the 'key' argument. Here is some example code regarding what the custom sort functions should look like:
def sortByName(elem):
return elem.name
def sortByFirstLanguage(elem, firstLanguage):
if elem.language == firstLanguage:
return 1
else:
return -1
def sortByLanguages(elem, possibleLanguages):
if elem.language in possibleLanguages:
return possibleLanguages.index(elem.language)
How exactly can I tell the 'key' argument to pass in the extra arguments 'firstLanguage' && 'possibleLanguages' to custom sorting functions as I have shown above?
The python sort method will sort a list in place, using only < comparisons between items. You have to pass it a function which maps each element to something which may be compares to other mapped elements so that the 'less than' relation gives the desired result.
Custom Sorting With key= The key function takes in 1 value and returns 1 value, and the returned "proxy" value is used for the comparisons within the sort. For example with a list of strings, specifying key=len (the built in len() function) sorts the strings by length, from shortest to longest.
Use sorted() and a lambda expression to sort a list by two fields. Call sorted(a_list, key = k) with k as lambda x: x[i], x[j] to sort list by the i -th element and then by the j -th element.
Arguments of sort and sorted Both sort and sorted have three keyword arguments: cmp , key and reverse .
As Ashish points out in the comments, we first need to combine these functions, since key
only accepts a single functions. If we return a sequence (list, tuple) of the function results, Python will do the right thing, only comparing later (farther right) elements if the earlier elements are equal (source).
I know of a couple ways to do this.
Using lambdas:
sortedBookList = sorted(
bookList,
key=lambda elem: (sortByName(elem),
sortByFirstLanguage(elem, firstLanguage),
sortByLanguages(elem, possibleLanguages)))
Using higher-order functions:
def key_combiner(*keyfuncs):
def helper(elem):
return [keyfunc(elem) for keyfunc in keyfuncs]
return helper
def sortByFirstLanguage(firstLanguage):
def helper(elem):
return elem.language == firstLanguage # True > False
return helper
def sortByLanguages(possibleLanguages):
def helper(elem):
if elem.language in possibleLanguages:
return possibleLanguages.index(elem.language)
return helper
sortedBookList = sorted(bookList,
key=key_combiner(sortByName,
sortByFirstLanguage(firstLanguage),
sortByLanguages(possibleLanguages))
Lambdas seem cleanest to me, so that's probably what I'd use.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With