pythonlistsortingdate-sorting

Custom sorting a list in python


I want to sort the following list with some elements as dates and some are Quarters.

input_ls = ['Nov-2015', 'Quarter 1, 2016', 'Jan-2016', 'Dec-2015',
           'Feb-2016', 'Quarter 4, 2015']

Expected output is as follows. How can I do this?

output_ls = ['Quarter 1, 2016', 'Feb-2016', 'Jan-2016', 'Quarter 4, 2015'
             'Dec-2015', 'Nov-2015']

Solution

  • Here is a solution using datetutil and regex:

    from dateutil import parser
    import re
    input_ls = ['Nov-2015', 'Quarter 1, 2016', 'Jan-2016', 'Dec-2015','Feb-2016', 'Quarter 4, 2015']
    res = []
    for x in input_ls:
        #Match x if it is having a digit followed by a comma followed by a space and followed by four digits
        qtr = re.findall('(\d),\s(\d{4})',x)
        #If match not found parse it as date by prefixing '1,' to the string
        if len(qtr) == 0:
            res.append(parse('1,' + x))
        #If matching then format it to a string format that is acceptable to the dateutil parser
        else:
            res.append(parse(str(int(qtr[0][0])*3)+'-30-'+qtr[0][1]))
    #Sort the output list
    out = zip(res,input_ls)
    out.sort()
    #Reverse it 
    out.reverse()
    

    And this is how the output will look like: enter image description here

    Here is another way of doing using sort key probably the most pythonic way - with help from Martijn Pieters

    from dateutil import parser
    import re
    input_ls = ['Nov-2015', 'Quarter 1, 2016', 'Jan-2016', 'Dec-2015','Feb-2016', 'Quarter 4, 2015']
    
    def sort_key(x):
        qtr = re.findall('(\d),\s(\d{4})',x)
        #If match not found parse it as date by prefixing '1,' to the string
        if len(qtr) == 0:
            return parse('1,' + x)
        #If matching then format it to a string format that is acceptable to the dateutil parser
        else:
            return parse(str(int(qtr[0][0])*3)+'-30-'+qtr[0][1])
    
    input_ls.sort(key=sort_key)
    

    And this is how the output will look like:

    enter image description here