For example, if I have a Person class
class Person:
def __init__(self, name: str, age: int):
self.name = name
self.age = age
def __repr__(self) -> str:
return f"({self.name}, {self.age})"
and a List of Person
persons = [
Person("Bob", 25),
Person("Alice", 25),
Person("Charlie", 23),
Person("Dave", 25),
]
I can sort the list by age in ascending order, and in case of a tie, sort by name in ascending order using the following method:
sorted_persons = sorted(persons, key=lambda p: (p.age, p.name))
Question:
However, I'm looking for a way to sort the list by age in ascending order and, in the event of a tie in age, sort by name in descending order. How could I achieve this in Python?
I've come up with one solution, as shown below, but it seems a bit inelegant. Is there a more succinct way to write a string comparison method that can handle all three cases (i.e., less than, equal to, and greater than)? For instance, Java has a s1.compareTo(s2) method that makes such comparisons straightforward.
Here's the solution I'm currently working with:
from functools import cmp_to_key
def compare(p1, p2):
cmp = p1.age - p2.age
if cmp != 0:
return cmp
if p1.name < p2.name:
return 1
elif p1.name > p2.name:
return -1
return 0
sorted_persons = sorted(persons, key=cmp_to_key(compare))
This code correctly sorts the persons list first by age in ascending order, and then by name in descending order when the ages are equal. However, I feel there should be a cleaner, more Pythonic way to handle this. Any suggestions?
Another solution:
For the purpose of sorting you can define custom str class where you override the __lt__ magic method (less than):
class reverse_cmp_string(str):
def __lt__(self, other):
return not str.__lt__(self, other)
sorted_persons = sorted(persons, key=lambda p: (p.age, reverse_cmp_string(p.name)))
print(sorted_persons)
Prints:
[(Charlie, 23), (Dave, 25), (Bob, 25), (Alice, 25)]
This snippet of code should do it. I ran it and the output looks right
sorted_persons = sorted(persons, key=lambda p: (-p.age, p.name), reverse=True)
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