Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python custom sort function for strings like 'Season Year'

Tags:

python

sorting

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:

  1. First sort by year

  2. 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?

like image 324
Tanishq dubey Avatar asked Aug 03 '15 18:08

Tanishq dubey


People also ask

Can sort () be used for strings in Python?

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.

How do you customize a sort function in Python?

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.

Can sort () sort strings?

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.

How do you sort chronologically in Python?

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.


2 Answers

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.

like image 116
Padraic Cunningham Avatar answered Nov 15 '22 21:11

Padraic Cunningham


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)
like image 26
JuniorCompressor Avatar answered Nov 15 '22 19:11

JuniorCompressor