Custom Sorting Logic for E-commerce Products
You've been tasked with building a feature for an e-commerce platform that allows users to sort products based on multiple criteria. This challenge will test your ability to implement a robust sorting algorithm that can handle complex sorting requirements, providing a better user experience by letting them find what they need quickly.
Problem Description
Your goal is to create a Python function that sorts a list of product dictionaries. Each product dictionary contains information such as its name, price, rating (out of 5), and stock_quantity. The sorting should be flexible, allowing for different primary and secondary sorting keys, as well as ascending or descending order for each key.
Requirements:
- The function should accept a list of product dictionaries as input.
- It should also accept a list of sorting criteria. Each criterion will be a tuple:
(key, order), wherekeyis a string representing the dictionary key to sort by (e.g., 'price', 'rating') andorderis a string, either 'asc' (ascending) or 'desc' (descending). - The sorting should be stable, meaning that if two products have the same value for the primary sorting key, their relative order should be preserved based on the next sorting key, and so on.
- The function should return a new list containing the sorted product dictionaries. The original list should not be modified.
Expected Behavior:
- The function should iterate through the provided sorting criteria in order.
- For each criterion, it should sort the list based on the specified key and order.
- The final output list should be sorted according to all criteria, with the first criterion having the highest precedence, followed by the second, and so on.
Edge Cases:
- Empty input list of products.
- List with only one product.
- Sorting criteria involving keys that might not exist in all product dictionaries (assume for this challenge that all keys will exist for simplicity, but be mindful of this in real-world scenarios).
- Zero or negative prices, ratings, or stock quantities.
Examples
Example 1:
Input:
products = [
{'name': 'Laptop', 'price': 1200, 'rating': 4.5, 'stock_quantity': 15},
{'name': 'Mouse', 'price': 25, 'rating': 4.0, 'stock_quantity': 50},
{'name': 'Keyboard', 'price': 75, 'rating': 4.0, 'stock_quantity': 30},
{'name': 'Monitor', 'price': 300, 'rating': 4.8, 'stock_quantity': 10}
]
sort_criteria = [('price', 'asc')]
Output:
[
{'name': 'Mouse', 'price': 25, 'rating': 4.0, 'stock_quantity': 50},
{'name': 'Keyboard', 'price': 75, 'rating': 4.0, 'stock_quantity': 30},
{'name': 'Monitor', 'price': 300, 'rating': 4.8, 'stock_quantity': 10},
{'name': 'Laptop', 'price': 1200, 'rating': 4.5, 'stock_quantity': 15}
]
Explanation: The products are sorted by price in ascending order.
Example 2:
Input:
products = [
{'name': 'Laptop', 'price': 1200, 'rating': 4.5, 'stock_quantity': 15},
{'name': 'Mouse', 'price': 25, 'rating': 4.0, 'stock_quantity': 50},
{'name': 'Keyboard', 'price': 75, 'rating': 4.0, 'stock_quantity': 30},
{'name': 'Monitor', 'price': 300, 'rating': 4.8, 'stock_quantity': 10}
]
sort_criteria = [('rating', 'desc'), ('price', 'asc')]
Output:
[
{'name': 'Monitor', 'price': 300, 'rating': 4.8, 'stock_quantity': 10},
{'name': 'Laptop', 'price': 1200, 'rating': 4.5, 'stock_quantity': 15},
{'name': 'Keyboard', 'price': 75, 'rating': 4.0, 'stock_quantity': 30},
{'name': 'Mouse', 'price': 25, 'rating': 4.0, 'stock_quantity': 50}
]
Explanation: Products are first sorted by rating in descending order. For products with the same rating (Keyboard and Mouse), they are then sorted by price in ascending order.
Example 3:
Input:
products = [
{'name': 'Phone A', 'price': 600, 'rating': 4.2, 'stock_quantity': 20},
{'name': 'Phone B', 'price': 700, 'rating': 4.2, 'stock_quantity': 5},
{'name': 'Phone C', 'price': 600, 'rating': 4.1, 'stock_quantity': 15}
]
sort_criteria = [('rating', 'desc'), ('price', 'asc'), ('stock_quantity', 'desc')]
Output:
[
{'name': 'Phone A', 'price': 600, 'rating': 4.2, 'stock_quantity': 20},
{'name': 'Phone B', 'price': 700, 'rating': 4.2, 'stock_quantity': 5},
{'name': 'Phone C', 'price': 600, 'rating': 4.1, 'stock_quantity': 15}
]
Explanation:
1. Sorted by rating (desc): Phone A and Phone B have 4.2, Phone C has 4.1.
2. For Phone A and Phone B (both 4.2 rating), sort by price (asc): Phone A (600) comes before Phone B (700).
3. The final order is Phone A, Phone B, Phone C. The third criterion ('stock_quantity', 'desc') does not affect the order in this specific case as all previous criteria uniquely ordered the items.
Constraints
- The input
productslist can contain between 0 and 1000 dictionaries. - Each product dictionary will have the keys:
'name'(string),'price'(integer or float),'rating'(float), and'stock_quantity'(integer). - Prices will be between 0 and 10000.
- Ratings will be between 0.0 and 5.0.
- Stock quantities will be between 0 and 1000.
- The
sort_criterialist can contain between 0 and 5 tuples. - Sorting keys in
sort_criteriawill always be one of'name','price','rating', or'stock_quantity'. - Sorting orders in
sort_criteriawill always be either'asc'or'desc'. - The solution should aim for an efficient sorting approach, ideally with a time complexity close to O(N log N) where N is the number of products.
Notes
- Python's built-in
sorted()function or thelist.sort()method are powerful tools for sorting. Consider how you can leverage theirkeyargument. - For multi-criteria sorting, you might need to combine multiple sorting operations or devise a custom key function that represents the combined sorting order.
- Remember that sorting in Python is stable by default, which is a requirement for this challenge.
- Think about how to handle the ascending and descending order requirement effectively. You might need to transform values for descending sorts within your key function.