0

I have a dictionary of times and counts. I need to sort the dict so that it is in ascending order by time. I need help getting the sort to do something useful. Right now I am dropping the AM/PM to remove complexity but I am aware that I'm running into a problem there since I'm losing information.

Calling

sorted(myDict, key = bytime_key)

with

def bytime_key(input):
    shorter_input = re.match(r'^(.*) \w\w$', input).group(1)
    time = datetime.strptime(shorter_input, '%m/%d/%Y %H:%M:%S')
    return(time)

is fine, save that it doesn't actually change the order, so I'm missing something fundamental here.

Sample dictionary

myDict = {'1/15/2016 10:41:00 AM': 11, '1/15/2016 10:43:00 AM': 4,
          '1/15/2016 10:22:00 AM': 46, '1/15/2016 10:30:00 AM': 15,
          '1/15/2016 10:59:00 AM': 34, '1/15/2016 12:06:00 PM': 12,
          '1/15/2016 11:42:00 AM': 11, '1/15/2016 12:22:00 PM': 1,
          '1/15/2016 12:18:00 PM': 5, '1/15/2016 10:52:00 AM': 6}
Łukasz Rogalski
  • 22,092
  • 8
  • 59
  • 93
Shawn Mehan
  • 4,513
  • 9
  • 31
  • 51
  • order of what? `dict` does not have any order, `sorted` returns a `list` and does not modify input in place. see [How to sort OrderedDict](http://stackoverflow.com/a/8031431/1176601) though – Aprillion Jan 15 '16 at 22:31

4 Answers4

2

strptime allows for %p directive.

%p Locale’s equivalent of either AM or PM. AM, PM (en_US); am, pm (de_DE) (1), (2)

Key function may be simplified to:

from datetime import datetime

result = sorted(myDict, key=lambda s: datetime.strptime(s, "%m/%d/%Y %H:%M:%S %p"))
expected = ['1/15/2016 10:22:00 AM', '1/15/2016 10:30:00 AM', 
            '1/15/2016 10:41:00 AM', '1/15/2016 10:43:00 AM',
            '1/15/2016 10:52:00 AM', '1/15/2016 10:59:00 AM', 
            '1/15/2016 11:42:00 AM', '1/15/2016 12:06:00 PM',
            '1/15/2016 12:18:00 PM', '1/15/2016 12:22:00 PM']
assert result == expected

Note that dictionaries are inherently unsorted structures. What you can do is perform sorting of keys / values / key-value pairs and create an ordered representation of data sorted in dictionary. And that's what your code does - it sorts keys.

Łukasz Rogalski
  • 22,092
  • 8
  • 59
  • 93
1

Standard Python dictionaries are unordered and will not preserve any ordering from a sort.

You could use the OrderedDict to order the items in the dictionary based on their insertion times.

from collections import OrderedDict

ordered_times = OrderedDict(sorted(myDict.keys(), key=bytime_key))
gnerkus
  • 11,357
  • 6
  • 47
  • 71
0

There are 2 problems that come to mind. 1st, dicts are not sortable. You might want to use an OrderedDict. Second, sorted doesn't sort the 1st argument, it returns a sorted copy of first argument.

Try changing the line in bytime_key from:

shorter_input = re.match(r'^(.*) \w\w$', input).group(1)

to

shorter_input = re.match(r'^(.*) \w\w$', input[0]).group(1)

Then get the OrderedDict using:

from collections import OrderedDict
my_sorted_dict = OrderedDict(sorted(myDict.iteritems(), key = bytime_key))
Charles L.
  • 5,795
  • 10
  • 40
  • 60
0

Sorted returns a new list, so it won't modify your dictionary. Consider using list.sort() to sort in place.

Dictionaries don't have an order associated with them. They are very fast (O(1)) at looking up items, but aren't as useful for other operations.

Consider using a list of tuples (timestamp, count) or an OrderedDictionary.

tmajest
  • 360
  • 1
  • 5