Python按日期排序的有序字典

3

我正在尝试使用有序字典(OrderedDict),这是Raymond Hettinger在Python pre2.7版本中的版本。我的键是日期。然而,它没有正确排序,我猜想可能是基于ID进行排序。

有人有什么建议吗?


你能提供一个日期的例子吗? - juanchopanza
1
你能给我们举个例子,你是如何尝试实现这个的吗?在我的系统(原始Python实现)上,它可以正常工作。 - utdemir
1
请注意,这是一个“有序”的字典,而不是“排序”的字典。(在我的软件工程课程中,我一直遇到了一些讲师甚至都没有理解“有序”和“排序”之间的区别。) - Chris Morgan
@Chris,你说得对,我误解了。我一开始以为这是一个已排序的字典。 - Jim Jeffries
2个回答

9
In [1]: from collections import OrderedDict

In [2]: import operator

In [3]: from datetime import date

In [4]: d = {date(2012, 1, 1): 123, date(2010,2,5): 542, date(2011,3,3):76 }

In [5]: d # Good old dict
Out[5]: #it seems sorted, but it isn't guaranteed to be that way.
{datetime.date(2010, 2, 5): 542,
 datetime.date(2011, 3, 3): 76,
 datetime.date(2012, 1, 1): 123}

In [6]: o = OrderedDict(sorted(d.items(), key=operator.itemgetter(0)))

In [7]: o #Now it is ordered(and sorted, because we give it by sorted order.).
Out[7]: OrderedDict([(datetime.date(2010, 2, 5), 542), (datetime.date(2011, 3, 3), 76), (datetime.date(2012, 1, 1), 123)])

实际上,当您使用date作为键时,它是有保证被排序的(记得称其为sorted而不是ordered),至少在CPython的当前实现中是如此。字典项的顺序是通过项目比较来确定的,这对于datetime.date是正确定义的。因此,如果您想要使用这样的键类型进行操作,可以使用dict而不是OrderedDict(并且您将记得添加有关所依赖的行为的注释 - Python的另一个实现可能不会破坏此行为)。 - Chris Morgan
@Chris,我看不出OrderedDict如何能够满足保持插入顺序和按项比较排序的承诺。而普通的dict使用哈希,不能假定任何顺序。 - juanchopanza
@Chris Morgan,在我的系统上,Python 2.7.2和Python 3.2.1中,字典并没有排序。 - utdemir
@utdemir 啊,我忘记使用itemgetter了... 它在性能和可读性方面都更好。 - Overmind Jiang
嗯,我好像在学习中犯了一个错误;我的字典理解是不正确的。抱歉。 - Chris Morgan
1
@Overmind:实际上,“,key=operator.itemgetter(0)”是多余的;dict.items()返回一个由(key, value)元组组成的列表。元组比较是通过先比较第一项,然后如果它们相同,则比较第二项,以此类推完成的。但是,第一项将全部不同,因为它们已被用作字典中的键。因此,它基本上意味着第一项比较(但速度更快)。 - Chris Morgan

4

OrderedDict是一种字典类型,它记住了插入顺序。因此,您需要手动按正确顺序插入键/值对。

# assuming unordered_dict is a dict that contains your data 
ordered_dict = OrderedDict()
for key, value in sorted(unordered_dict.iteritems(), key=lambda t: t[0]):
    ordered_dict[key] = value

编辑:请参考utdemir的答案,这里有一个更好的例子。使用operator.itemgetter可以获得更好的性能(比我下面提供的基准测试代码快60%),并且它是更好的编码风格。而且你可以直接将OrderedDict应用到sorted(...)

a = (1, 2)

empty__func = 0
def empty():
    for i in xrange(N_RUNS):
        empty__func

lambda_func = lambda t: t[0]
def using_lambda():
    for i in xrange(N_RUNS):
        lambda_func(a)

getter_func = itemgetter(0)
def using_getter():
    for i in xrange(N_RUNS):
        getter_func(a)

@juanchopanza 不,我只是在循环中比较了普通的itemgetter和lambda。请参考上面的代码。 - Overmind Jiang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接