Custom Sorting with Complex Object Comparison
In Python, sorting is a fundamental operation. While Python's built-in sort() method and sorted() function are powerful, they rely on default comparison logic or a key function that transforms objects before comparison. However, there are scenarios where you need to define custom, complex comparison logic that directly compares objects based on multiple attributes, potentially with varying priorities or conditional rules. This challenge will test your ability to implement such custom comparison logic.
Problem Description
You are tasked with sorting a list of Book objects. Each Book object has the following attributes: title (string), author (string), year (integer), and rating (float).
Your sorting criteria are as follows:
- Primary Sort: Sort by
yearin ascending order. - Secondary Sort: If two books have the same
year, sort them byratingin descending order. - Tertiary Sort: If two books have the same
yearandrating, sort them bytitlein alphabetical (ascending) order.
You should implement this sorting logic using Python's functools.cmp_to_key to convert a traditional comparison function into a key function suitable for sorted().
Key Requirements:
- Define a
Bookclass withtitle,author,year, andratingattributes. - Implement a comparison function that takes two
Bookobjects as input and returns:-1if the first book should come before the second.1if the first book should come after the second.0if they are considered equal for sorting purposes (though the tertiary sort will likely prevent this for distinct books).
- Use
functools.cmp_to_keyto adapt your comparison function. - Sort a given list of
Bookobjects using the adapted key and thesorted()function.
Expected Behavior:
The sorted() function should return a new list of Book objects ordered according to the specified criteria.
Edge Cases to Consider:
- Empty input list.
- Books with identical
yearandratingbut differenttitles.
Examples
Example 1:
Input:
books_data = [
{"title": "The Hitchhiker's Guide to the Galaxy", "author": "Douglas Adams", "year": 1979, "rating": 4.5},
{"title": "Pride and Prejudice", "author": "Jane Austen", "year": 1813, "rating": 4.8},
{"title": "1984", "author": "George Orwell", "year": 1949, "rating": 4.7},
{"title": "To Kill a Mockingbird", "author": "Harper Lee", "year": 1960, "rating": 4.9},
{"title": "The Great Gatsby", "author": "F. Scott Fitzgerald", "year": 1925, "rating": 4.6},
]
# Assume Book class and comparison function are defined
# sorted_books = sorted(books_list, key=cmp_to_key(compare_books))
Output:
[
Book(title='Pride and Prejudice', author='Jane Austen', year=1813, rating=4.8),
Book(title='The Great Gatsby', author='F. Scott Fitzgerald', year=1925, rating=4.6),
Book(title='1984', author='George Orwell', year=1949, rating=4.7),
Book(title='To Kill a Mockingbird', author='Harper Lee', year=1960, rating=4.9),
Book(title="The Hitchhiker's Guide to the Galaxy", author='Douglas Adams', year=1979, rating=4.5)
]
Explanation: The books are sorted primarily by year (1813, 1925, 1949, 1960, 1979). There are no ties in year, so the secondary and tertiary sorts are not demonstrated here.
Example 2:
Input:
books_data = [
{"title": "Book C", "author": "Author Y", "year": 2020, "rating": 4.2},
{"title": "Book A", "author": "Author X", "year": 2020, "rating": 4.5},
{"title": "Book B", "author": "Author Z", "year": 2020, "rating": 4.5},
{"title": "Book D", "author": "Author W", "year": 2019, "rating": 4.1},
]
# Assume Book class and comparison function are defined
# sorted_books = sorted(books_list, key=cmp_to_key(compare_books))
Output:
[
Book(title='Book D', author='Author W', year=2019, rating=4.1),
Book(title='Book A', author='Author X', year=2020, rating=4.5),
Book(title='Book B', author='Author Z', year=2020, rating=4.5),
Book(title='Book C', author='Author Y', year=2020, rating=4.2)
]
Explanation:
- "Book D" is sorted first because it has the earliest year (2019).
- The remaining books are from 2020.
- "Book A" and "Book B" have the highest rating (4.5). Between them, they are sorted by title alphabetically: "Book A" comes before "Book B".
- "Book C" has a lower rating (4.2) and comes last among the 2020 books.
Example 3 (Edge Case):
Input:
books_data = []
# Assume Book class and comparison function are defined
# sorted_books = sorted(books_list, key=cmp_to_key(compare_books))
Output:
[]
Explanation: An empty input list results in an empty output list.
Constraints
- The number of books in the list will be between 0 and 1000 (inclusive).
titleandauthorwill be non-empty strings.yearwill be an integer between 1000 and 3000.ratingwill be a float between 0.0 and 5.0.- The sorting operation should be efficient enough to complete within a reasonable time for the given constraints.
Notes
- You will need to import the
functoolsmodule forcmp_to_key. - Consider how to handle comparisons for each criterion in your comparison function.
- Remember that
cmp_to_keyrequires a function that adheres to the traditional comparison function signature (returning -1, 0, or 1). - Implementing
__eq__and__repr__methods for yourBookclass will be helpful for testing and debugging.