Introduction

Sorting is used to arrange the data in certain order. sorted() is built-in function in python that returns a sorted list of the iterable object i.e. list, dictionary, and tuple. Python lists have a built-in list.sort() method that modifies the list in-place.

Syntax of sorted() function is

sorted(iterable, key=None, reverse=False)

where

  • iterable : It is a sequence (string, tuple, list) or collection (set, dictionary) or any other iterator.
  • key (Optional) : Specifies a function of one argument that is used to extract a comparison key from each element in iterable. Default value is None (compare the elements directly).
  • reverse (Optional) : If True, the sorted list is reversed. Default value is False.

sorted() return a new sorted list from the items in iterable. It is guaranteed to be stable i.e. it will not change the relative order of elements that compare equal.

Examples

Below example sorts list of scores in ascending and descending order.

scores = [82, 67, 94, 73, 79, 86, 58, 91, 89, 71, 88, 77, 84]

# Sort in ascending order
sortedScores = sorted(scores)
print(sortedScores)

# Output
# [58, 67, 71, 73, 77, 79, 82, 84, 86, 88, 89, 91, 94]


# Sort in descending order
sortedScores = sorted(scores, reverse=True)
print(sortedScores)

# Output
# [94, 91, 89, 88, 86, 84, 82, 79, 77, 73, 71, 67, 58]

sorted() can also be used to sort string, dictionary and tuple as shown in following example. A dictionary is sorted based on the key.

# Vowels list
py_list = ['e', 'a', 'u', 'o', 'i']
print(sorted(py_list))

# Output 
# ['a', 'e', 'i', 'o', 'u']

# String
py_string = 'Python'
print(sorted(py_string))

# Output 
# ['P', 'h', 'n', 'o', 't', 'y']

# Tuple soritng
py_tuple = ('e', 'a', 'a', 'o', 'i')
print(sorted(py_tuple))

# Output
# ['a', 'a', 'e', 'i', 'o']

# Word list
py_list = ['cat', 'dog', 'mat', 'hat', 'fig']
print(sorted(py_list))

# Output
# ['cat', 'dog', 'fig', 'hat', 'mat']

py_dict = {2: 'ball', 1: 'apple'}
print(sorted(py_dict))

# Output
# [1, 2]

Custom Sorting Using Key

As described above, sorted() takes an optional parameter key. key function transforms each element before comparison. It takes in one parameter and returns one value. Returned value is used for the comparisons within the sort.

In the following example list having custom type is sorted using key function.

# the key parameter can be used to sort complex objects
class Item():
    def __init__(self, name, price, discount):
        self.name = name
        self.price = price
        self.discount = discount

    def __repr__(self):
        return repr((self.name, self.price, self.discount))

    def getDiscount(self):
        return self.discount


fruitList = [
    Item("Apple", 50, 20),
    Item("Mango", 40, 50),
    Item("Banana", 35, 15),
    Item("Kiwi", 65, 10)
]

# Function to use as key parameter in sorted()
def prodsort(product):
    return product.price

# 1. Sorting using prodsort
print(sorted(fruitList, key=prodsort))

# Output
# [('Banana', 35, 15), ('Mango', 40, 50), ('Apple', 50, 20), ('Kiwi', 65, 10)]

# 2. Sorting using price field
print(sorted(fruitList, key=lambda p: p.price))

# Output
#[('Banana', 35, 15), ('Mango', 40, 50), ('Apple', 50, 20), ('Kiwi', 65, 10)]

# 3. Sorting using method
print(sorted(fruitList, key=lambda p: p.getDiscount()))

# Output
# [('Kiwi', 65, 10), ('Banana', 35, 15), ('Apple', 50, 20), ('Mango', 40, 50)]

Sorting with Multiple Parameter

Consider the fruit list in below code snippet. We want to sort the list in such a way that the fruit with lowest price is in the beginning. In case the of fruit with equal price, it must be sorted such that fruit with lower discount comes first. Sorting based on multiple parameter can be achieved by returning tuple instead of a number. Two tuples can be compared by comparing their elements starting from first. If elements are equal, the second element is compared, and so on.

# the key parameter can be used to sort complex objects
class Item():
    def __init__(self, name, price, discount):
        self.name = name
        self.price = price
        self.discount = discount

    def __repr__(self):
        return repr((self.name, self.price, self.discount))

    def getDiscount(self):
        return self.discount


fruitList = [
    Item("Apple", 50, 20),
    Item("Mango", 40, 50),
    Item("Banana", 35, 15),
    Item("Kiwi", 65, 10),
    Item("Pear", 50, 10),
]

# Function to use as key parameter in sorted()
def prodsort(product):
    return (product.price, product.discount)

# Sort on price. If price are same, then use discount
print(sorted(fruitList, key=prodsort))

# Output
# [('Banana', 35, 15), ('Mango', 40, 50), ('Pear', 50, 10), ('Apple', 50, 20), ('Kiwi', 65, 10)]

Sorting using Operator Module Function

Python operator module has itemgetter(), attrgetter(), and a methodcaller() function. These functions provide easy ways to select fields i.e.

  • attrgetter() retrieves a given attribute or property from an object
  • itemgetter() retrieves an item at a given index in a collection
  • methodcaller() calls the given method on the object
# the key parameter can be used to sort complex objects
from operator import attrgetter, methodcaller, itemgetter

class Product():
    def __init__(self, name, price, discount):
        self.name = name
        self.price = price
        self.discount = discount

    def __repr__(self):
        return repr((self.name, self.price, self.discount))

    def discountPrice(self):
        return self.price - (self.price * self.discount)

prodList = [
    Product("A", 50, 0.05),
    Product("C", 40, 0.15),
    Product("B", 35, 0.0),
    Product("E", 65, 0.20),
    Product("D", 70, 0.12)
]

# 1. Using the attrgetter method
print(sorted(prodList, key=attrgetter("price"), reverse=True))

# Output
# [('D', 70, 0.12), ('E', 65, 0.2), ('A', 50, 0.05), ('C', 40, 0.15), ('B', 35, 0.0)]

# 2. Using methodcaller to invoke a method
print(sorted(prodList, key=methodcaller("discountPrice")))

# Output
# [('C', 40, 0.15), ('B', 35, 0.0), ('A', 50, 0.05), ('E', 65, 0.2), ('D', 70, 0.12)]

inventory = [("C", 5), ("A", 2), ("B", 4), ("E", 7), ("D", 4)]

# 3. Use itemgetter to retrieve an index
print(sorted(inventory, key=itemgetter(0)))

# Output
# [('A', 2), ('B', 4), ('C', 5), ('D', 4), ('E', 7)]