0

I am grouping a list of objects together by their timestamp:

object_list = [
{
    timestamp: datetime.strptime("01/01/2014", "%d/%m/%y"),
},
{
    timestamp: datetime.strptime("12/05/2014", "%d/%m/%y"),
},
{
    timestamp: datetime.strptime("03/01/2014", "%d/%m/%y"),
},
{
    timestamp: datetime.strptime("01/01/2014", "%d/%m/%y"),
}]

date_grouped_objects = defaultdict(list)

for obj in object_list:
    date_grouped_objects[obj.timestamp].append(obj)

Which gives me exactly what I want, a list of objects grouped together by their timestamp attribute.

Question: I now want to sort date_grouped_objects by the keys (the timestamps), but it isn't clear how you can use sorted to achieve this? So the most group with the most recent date would be last

So what I'm after is:

[
    ["01/01/2014"] = [...],
    ["03/01/2014"] = [...],
    ["12/05/2014"] = [...],
]

Where the keys are actually date objects, not strings.

martineau
  • 119,623
  • 25
  • 170
  • 301
Hanpan
  • 10,013
  • 25
  • 77
  • 115
  • So what have you tried, and what is wrong with it? Which of those are you having a problem with? Sorting? Making the date objects from the strings? What is your output data structure supposed to be - it is a cross between a list and some assignments and ??? – jonrsharpe Jun 23 '14 at 22:09
  • Edited my question. I am just trying to figure out how sort the resulting date_grouped_objects by it's keys – Hanpan Jun 23 '14 at 22:12
  • 2
    Please provide a [minimal example](http://stackoverflow.com/help/mcve) that runs and demonstrates the problem. For example, your data doesn't match the `strptime` template, and `timestamp` isn't defined. And, again, what is the output you expect - what have written there **is not** a valid Python structure. – jonrsharpe Jun 23 '14 at 22:16

3 Answers3

8

Like most Map implementations, defaultdict isn't ordered1 and thus itself can't be "sorted".

However, the contained items() pairings can be sorted and the result is a sequence (list), not a map (dict). This iterable of tuples, where the sort key comes first, can be sorted trivially because or the default-ordering imposed by tuples is established pair-wise from the left.

d = {'c': 1, 'a': 2, 'b': 3}
s = sorted(d.items())
# s -> [('a', 2), ('b', 3), ('c', 1)]

For more complex cases, a custom comparison function or a key selector function can be used for the sort; these both produce the same output as above.

s = sorted(d.items(), lambda a, b: a[0] >= b[0])
s = sorted(d.items(), key = lambda i: i[0])

1An OrderedDict could be used to maintain the insertion-ordering, once the keys are sorted.

An OrderedDict is a dict that remembers the order that keys were first inserted..

However, I do not recommend basing algorithms on this special guarantee.

import collections
od = collections.OrderedDict(s)
user2864740
  • 60,010
  • 15
  • 145
  • 220
4

You could use theOrderedDefaultdictclass from another answer of mine to do something like the following:

from datetime import datetime
from ordereddefaultdict import OrderedDefaultdict

object_list = [{'timestamp': datetime.strptime("01/01/2014", "%d/%m/%Y")},
               {'timestamp': datetime.strptime("12/05/2014", "%d/%m/%Y")},
               {'timestamp': datetime.strptime("03/01/2014", "%d/%m/%Y")},
               {'timestamp': datetime.strptime("01/01/2014", "%d/%m/%Y")},]

date_grouped_objects = OrderedDefaultdict(list)

for obj in sorted(object_list):
    key = obj['timestamp'].strftime("%d/%m/%Y")  # convert datetime to string
    date_grouped_objects[key].append(obj)

for key, value in date_grouped_objects.iteritems():
    print '[{!r}] = {}'.format(key, value)

Output:

['01/01/2014'] = [{'timestamp': datetime.datetime(2014, 1, 1, 0, 0)},
                  {'timestamp': datetime.datetime(2014, 1, 1, 0, 0)}]
['03/01/2014'] = [{'timestamp': datetime.datetime(2014, 1, 3, 0, 0)}]
['12/05/2014'] = [{'timestamp': datetime.datetime(2014, 5, 12, 0, 0)}]
Community
  • 1
  • 1
martineau
  • 119,623
  • 25
  • 170
  • 301
  • 2
    You don't need to have it in Python 3.6+. You could just use defaultdict, which is maintaining order of keys by default – Mysterion Feb 10 '21 at 18:22
0

Use the builtin sorted method. It works for both values and keys. You can use the key and reverse arguments for complex sorts

Michael
  • 713
  • 10
  • 27