0

So, I have a list of strings that are all formatted in Month DayNumber, like

['March 1', 'March 9', 'April 14', 'March 12']

I need to sort the list so all the dates are in the order they would be in a calendar. Any tips? Is there a built-in method that might be able to help me, or should I design a custom sort using a lambda?

HunBurry
  • 113
  • 14

5 Answers5

1

You may want to review this question: Converting string into datetime

After parsing you could sort by date based on the values obtained from parsing string into datetime objects (which are sortable).

sophros
  • 14,672
  • 11
  • 46
  • 75
  • I had done that, and had the code (sorted(testing, key=lambda x: datetime.datetime.strptime(x, '%m-%Y-%d'))), but it did not work so I went back to the drawing board. – HunBurry Mar 19 '18 at 17:56
  • are you sure `%Y` should have been there? I would just use `'%B %d'` (where `%B` is the full month name in the current locale). It worked for me like a charm on the data you provided. – sophros Mar 19 '18 at 17:59
  • my data was different when I wrote that orginally, my bad. The issue is that the data is getting passed as a list, not a string, and throwing an error. I'll look into it, thanks for the help. – HunBurry Mar 19 '18 at 18:09
1

You can also leverage the calendar module:

from calendar import month_name
months = list(month_name)

def parser (text):
    """Parses 'englishmonthname_whitespace_day-number' into string 'monthNR.dayNr'. 
    Will pad a zero to allow for string based sorting."""  
    try:
        month,day = text.split()
        monthAsIdx = months.index(month.strip())
        return '{:02d}.{:02d}'.format(monthAsIdx,int(day)) # return index in list.days
    except (ValueError, IndexError): # ValueError if not enough elements in string,
                                     # IndexError if not in list of month names
        return "99.99" # put last - all errors are put last w/o specific reordering

dates = ['TooFew', 'EnoughBut NotInList', 'March 1', 'March 9', 'April 14', 'March 12'] 

for n in dates:
    print(parser(n))


sortedDates = sorted(dates, key=lambda x: parser(x))

print(sortedDates)

Output:

# result of parser()
99.99
99.99
03.01
03.09
04.14
03.12

# sorted by key/lambda
['March 1', 'March 9', 'March 12', 'April 14', 'TooFew', 'EnoughBut NotInList'] 
Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
1

One way is to use numpy.argsort combined with datetime library.

import numpy as np
from datetime import datetime

lst = ['March 1', 'March 9', 'April 14', 'March 12']

arr = np.array(lst)
res = arr[np.argsort([datetime.strptime(i+' 2018', '%B %d %Y') for i in lst])].tolist()

Result:

['March 1', 'March 9', 'March 12', 'April 14']

This is possible because, internally, dates are just numeric data. In this case, we attach an arbitrary year 2018 to create datetime objects.

jpp
  • 159,742
  • 34
  • 281
  • 339
1

You can use pandas module. Install it with pip.

You can do something like this:

import pandas as pd

dates = ['March 1', 'March 9', 'April 14', 'March 12']

df = pd.DataFrame(dates)
df = pd.to_datetime(df[0], format="%B %d")

df=df.sort_values() 

print (df)

This datetime format can be very useful like for example if you want the day or the month of an element of the list just do:

df.month
df.day
hopieman
  • 399
  • 7
  • 22
0

Possibilities:

  • Use a dictionary and use key/value
  • Use string matching (regex)
  • Many more ...

Or google and use any of these:

To provide a possible solution:

Input_list = [{'month':'March', 'day':30}, {'month':'March', 'day':10}]

newlist = sorted(Input_list, key=lambda k: k['month']) 
Benedict K.
  • 836
  • 2
  • 8
  • 22