I have a list of the form 'Season Year':
['Fall 2014', 'Spring 2015', 'Fall 2008', 'Spring 2008']
And when sorted, the list should look like this:
['Spring 2015', 'Fall 2014', 'Spring 2008', 'Fall 2008']
Hence, the rules for sorting are:
First sort by year
Sort by season: 'Spring' then 'Fall'
I currently have a function called lcmp
that I use on my list like this: myList.sort(lcmp)
.
>>> def lcmp(a,b):
... c = a.split()
... d = b.split()
... if(c[1]>d[1]):
... if(c[0]>d[0]):
... return 1
... else:
... return -1
... else:
... if(c[0]>d[0]):
... return 1
... else:
... return 0
...
This works for sorting by year, but does not work for the season, even though I have specified that type of sorting. Why is this happening?
Python sorted() Function The sorted() function returns a sorted list of the specified iterable object. You can specify ascending or descending order. Strings are sorted alphabetically, and numbers are sorted numerically. Note: You cannot sort a list that contains BOTH string values AND numeric values.
In Python, we can write custom sort functions that work with sort() and sorted() . The value of the key parameter should be a function that takes a single argument and returns a key for sorting purposes.
The sort() method is generic. It only expects the this value to have a length property and integer-keyed properties. Although strings are also array-like, this method is not suitable to be applied on them, as strings are immutable.
To sort a list of numbers in Python in increasing order, just call the sorted() method on a list of numbers. This method defaults to sorting the numbers in increasing order.
Just using -year
to reverse the sort by year as the first key and the result of seas != "Spring"
to break the ties using key=sort_function
.
l = ['Fall 2014', 'Spring 2015', 'Fall 2008', 'Spring 2008']
def key(x):
seas,year = x.split()
return -int(year), seas != "Spring"
l.sort(key=key)
There is no way your function will work even if you use myList.sort(key=lcmp)
as you are passing single strings so you don't have a and b to split. This will also work for python 2 or 3.
One of the errors is that you don't check correctly for equality. What you return when c[1] < d[1]
and c[0] < d[0]
? The answer is zero, which is incorrect. Also you should declare cmp
argument in sort. What you can do is the following:
seasons = {
'Spring': 1,
'Summer': 2,
'Fall': 3,
'Winter': 4,
}
def lcmp(a, b):
a_season, a_year = a.split()
b_season, b_year = b.split()
return int(b_year) - int(a_year) or seasons[a_season] - seasons[b_season]
l = ['Fall 2014', 'Spring 2015', 'Fall 2008', 'Spring 2008']
l.sort(cmp=lcmp)
Result:
['Spring 2015', 'Fall 2014', 'Spring 2008', 'Fall 2008']
And if you want to play with iterators:
from itertools import ifilter, izip
def lcmp(a, b):
it = (
f(y) - f(x)
for x, y, f in izip(
reversed(a.split()),
reversed(b.split()),
(int, lambda _: -seasons[_])
)
)
return next(ifilter(None, it), 0)
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