如何根据键对defaultdict排序?

1 投票
3 回答
18529 浏览
提问于 2025-04-18 10:49

我正在根据时间戳把一组对象归类在一起:

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)

这样做的结果正是我想要的,得到了一组根据时间戳属性归类的对象。

问题是:我现在想根据这些时间戳对 date_grouped_objects 进行排序,但不太清楚如何使用 sorted 来实现这个目标?我希望最新的日期组排在最后。

所以我想要的是:

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

其中这些键实际上是日期对象,而不是字符串。

3 个回答

0

使用内置的排序方法。这个方法可以同时对值和键进行排序。你还可以利用关键字和反向参数来进行更复杂的排序。

8

像大多数地图(Map)实现一样,defaultdict 是没有顺序的1,所以它本身不能被“排序”。

不过,里面的items()配对是可以排序的,排序后的结果是一个序列(列表),而不是一个字典(dict)。这个包含元组的可迭代对象,排序时会把排序的关键字放在前面,因为元组的默认排序是从左到右一对一地进行的。

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

对于更复杂的情况,可以使用自定义的比较函数或者关键字选择函数来进行排序;这两种方法的输出结果是一样的。

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

1可以使用OrderedDict来保持插入顺序,一旦键被排序。

OrderedDict 是一种字典,它记住了键最初插入的顺序。

不过,我不建议在算法中依赖这种特殊的保证。

import collections
od = collections.OrderedDict(s)
5

你可以使用我在另一个回答中提到的OrderedDefaultdict类,来做类似下面的事情:

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)

输出结果:

['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)}]

撰写回答