Sort in pythonic way
Sorting data is a fundamental operation in programming, and Python offers a powerful built-in function to accomplish this task efficiently: the sorted() function. Embracing the Pythonic way means leveraging these built-in tools to write concise and readable code.
When it comes to sorting, Python's sorted() function stands out for its simplicity and versatility. Whether you're dealing with lists, tuples, dictionaries, or any iterable object, sorted() can swiftly arrange your data in ascending or descending order, making it an indispensable tool for developers across various domains.
Let's delve into how we can harness the power of sorted() to organize our data effectively. 😎
Sorting a simple List
list_of_numbers = [500,200,400,300,600]
print(sorted(list_of_numbers))
Output:
[200, 300, 400, 500, 600]
When we utilize the sorted() function in Python to sort a list of numbers, it's essential to understand that this function doesn't alter the original list. Instead, it returns a new list containing the sorted elements while leaving the original list intact. This behavior ensures data integrity and allows for a non-destructive approach to sorting.
Sorting a list in a descending order
list_of_numbers = [500,200,400,300,600]
print(sorted(list_of_numbers, reverse=True))
Output:
[600, 500, 400, 300, 200]
We can also sort a list in descending order by utilizing a parameter provided by the sorted function which is reverse=True.
Sorting complex objects
Sorting isn't limited to simple data types like numbers; it's often necessary to sort more complex objects, such as dictionaries or custom-defined classes, based on specific criteria. Python's sorted() function provides a powerful solution to this challenge through its key parameter, allowing us to define custom sorting criteria tailored to the structure of our data.
lets illustrate with few examples below.
# sorting a list of tuple by it's index
list_of_widget = [("widget A",4),("widget B",2),("widget C",5),("wideget D",1)]
print(sorted(list_of_widget,key=lambda i: i[1]))
Output:
[('wideget D', 1), ('widget B', 2), ('widget A', 4), ('widget C', 5)]
In the above example, we have a list called list_of_widget containing tuples. Each tuple represents a widget, where the first element is the widget's name (a string), and the second element is its corresponding value (an integer).
We're using the sorted() function to sort the list_of_widget based on the second element (index 1) of each tuple, which represents the widget's value. The key parameter allows us to specify a function (in this case, a lambda function) that extracts the sorting key from each element of the list. Here, the lambda function lambda i: i[1] takes an item i (which is a tuple), and returns its second element (index 1), i.e., the widget's value. So, when sorted() executes with this lambda function as the key, it sorts list_of_widget based on the widget values, in ascending order.
Lets sort a custom class
class Product:
def __init__(self,name,price,discount):
self.name = name
self.price = price
self.discount = discount
def discount_price(self):
return self.price * self.discount
def __repr__(self):
return f"{self.name} : ( {self.price} , {self.discount_price()} )"
prod_list = [
Product("Headphone",10,0.05),
Product("monitors",100,0.01),
Product("desk",250,0.02),
Product("keyboard",80,0.05),
Product("mouse",50,0.05),
]
sorted_prod_list = sorted(prod_list,key=lambda p: p.price)
Output:
[Headphone : ( 10 , 0.5 ), mouse : ( 50 , 2.5 ), keyboard : ( 80 , 4.0 ), monitors : ( 100 , 1.0 ), desk : ( 250 , 5.0 )]
In the above example, we define a class Product representing a product. It has attributes name, price, and discount, along with a method discount_price() to calculate the discounted price of the product. Additionally, the __repr__ method is overridden to provide a string representation of the product object. Then we created a list prod_list containing instances of the Product class, representing different products along with their prices and discounts.
The sorted() function is used to sort the prod_list based on the price attribute of each Product object. The key parameter takes a lambda function lambda p: p.price, which extracts the price of each product p and uses it as the sorting key. After sorting, sorted_prod_list contains the Product objects sorted by their prices in ascending order. We can also sort it descending by just passing the reverse=True parameter after the key parameter as well.
class Product:
...
sorted_prod_list = sorted(prod_list,key=lambda p: p.price,reverse=True)
Output:
[desk : ( 250 , 5.0 ), monitors : ( 100 , 1.0 ), keyboard : ( 80 , 4.0 ), mouse : ( 50 , 2.5 ), Headphone : ( 10 , 0.5 )]
Sorting using attrgetter, methodcaller function
While lambda functions are versatile and commonly used for extracting attributes or calling methods when sorting, Python's operator module offers even more concise and efficient alternatives: attrgetter and methodcaller. These functions provide a cleaner and more readable approach for sorting objects based on their attributes or method results.
Lets illustrate with example below
Class Product:
...
# sorting by using attrgetter
sorted_prod_list = sorted(prod_list,key=attrgetter("price"))
Output:
[Headphone : ( 10 , 0.5 ), mouse : ( 50 , 2.5 ), keyboard : ( 80 , 4.0 ), monitors : ( 100 , 1.0 ), desk : ( 250 , 5.0 )]
The attrgetter function extracts the price attribute for each product as a key to sort the prod_list by using sorted function.
Class Product:
...
# sorting by using methodcaller
sorted_prod_list = sorted(prod_list,key=methodcaller("discount_price"))
Output:
[Headphone : ( 10 , 0.5 ), monitors : ( 100 , 1.0 ), mouse : ( 50 , 2.5 ), keyboard : ( 80 , 4.0 ), desk : ( 250 , 5.0 )]
Similarly methodcaller calls the discout_price method of each product which returns a value then used as a key to sort the prod_list by using sorted function.
So in summary, Python's sorted() function stands as a versatile and powerful tool for sorting data structures with ease and efficiency. Whether sorting simple lists of elements or more complex objects with custom-defined attributes, sorted() provides a straightforward and flexible solution. By leveraging parameters like key and reverse, developers can tailor sorting behavior to meet specific requirements, ensuring clarity and precision in their code. Additionally, alternatives such as attrgetter and methodcaller from the operator module offer cleaner and more efficient approaches for extracting attributes or calling methods when sorting objects. Overall, sorted() function adheres to Python's commitment to simplicity, readability, and practicality, making it a cornerstone of sorting operations in Python programming.