Reputation: 1542
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?
Upvotes: 9
Views: 1750
Reputation: 20025
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)
Upvotes: 2
Reputation: 180481
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.
Upvotes: 5
Reputation: 122466
You should also take into account the cases where the compared values are equal:
def lcmp(a,b):
c = a.split()
d = b.split()
if c[1] > d[1]:
return 1
elif c[1] == d[1]:
if c[0] > d[0]:
return -1
elif c[0] == d[0]:
return 0
else:
return 1
else:
return -1
You can then sort the data using myList.sort(lcmp)
or myList.sort(cmp=lcmp)
Upvotes: 0