使用其构造函数初始化OrderedDict的正确方法,使其保留初始数据的顺序?


124

初始化有序词典(OD)以便保留初始数据顺序的正确方法是什么?

from collections import OrderedDict

# Obviously wrong because regular dict loses order
d = OrderedDict({'b':2, 'a':1}) 

# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b',2), ('a', 1)])

# What about using a list comprehension, will 'd' preserve the order of 'l'
l = ['b', 'a', 'c', 'aa']
d = OrderedDict([(i,i) for i in l])

题:

  • OrderedDict在初始化时是否会保留元组列表的顺序,元组的元组或列表的元组或列表的列表等的顺序(上述第二和第三示例)?

  • 如何验证是否OrderedDict实际维持订单?由于a dict具有不可预测的顺序,如果我的测试向量幸运地具有与dict不可预测的顺序相同的初始顺序,该怎么办?例如,如果不是d = OrderedDict({'b':2, 'a':1})我写d = OrderedDict({'a':1, 'b':2}),我可能会错误地得出结论认为该顺序已保留。在这种情况下,我发现a dict是按字母顺序排列的,但这可能并不总是正确的。什么是使用反例来验证数据结构是否保留顺序的可靠方法,而无需反复尝试测试向量,直到一个中断为止?

PS:我将在此留出参考:“ OrderedDict构造函数和update()方法都接受关键字参数,但是它们的顺序丢失了,因为Python的函数使用常规无序字典来调用语义传递关键字参数”

PPS:希望将来,OrderedDict也将保留kwarg的顺序(示例1):http : //bugs.python.org/issue16991


10
具有讽刺意味的是,用(非空)dict初始化OrderedDict是错误的事情……可以说这将导致警告,因为它可能违反了用户的意图。
smci

3
在python3.6之后,OrderDict(b=2, a=1)也是一种正确的方法。参见PEP 468
IvanaGyro

Answers:


90

OrderedDict将保留其有权访问的任何订单。将有序数据传递给它进行初始化的唯一方法是传递键值对的列表(或更普遍地讲,是可迭代的),如最后两个示例中所示。正如您链接的文档所述,当您传入关键字参数或dict参数时,OrderedDict无法访问任何顺序,因为其中的任何顺序都在OrderedDict构造函数看到之前被删除。

请注意,在上一个示例中使用列表推导并没有什么改变。OrderedDict([(i,i) for i in l])和之间没有区别OrderedDict([('b', 'b'), ('a', 'a'), ('c', 'c'), ('aa', 'aa')])。评估列表理解并创建列表,并将其传入;OrderedDict对它的创建方式一无所知。


74
# An OD is represented by a list of tuples, so would this work?
d = OrderedDict([('b', 2), ('a', 1)])

是的,那行得通。根据定义,列表总是按照其表示方式进行排序。这也适用于列表理解,生成的列表的提供方式与提供数据的方式相同(即,来自列表的来源将是确定性的,来源于setdict不那么多)。

如何验证是否OrderedDict实际维持订单。由于字典具有不可预测的顺序,如果我的测试向量幸运地具有与字典的不可预测顺序相同的初始顺序,该怎么办?例如,如果不是d = OrderedDict({'b':2, 'a':1})我写d = OrderedDict({'a':1, 'b':2}),我可能会错误地得出结论认为该顺序已保留。在这种情况下,我发现a dict是按字母顺序排列的,但这可能并不总是正确的。也就是说,使用反例来验证数据结构是否保留顺序还是一种可靠的方法是一种可靠的方法,可以反复尝试测试向量,直到一个中断。

您保留2元组的源列表作为参考,并在进行单元测试时将其用作测试用例的测试数据。遍历它们并确保维持订单。


关于验证顺序:如果我的2元组是不可预测的,我该如何确保它会破坏命令的顺序?这是关于任何数据结构的通用问题,也许我应该将其与这个问题分开。
点击

1
您无法确定性地破坏本质上不确定的事物。
metatoaster

1
那么测试这种事情的正确方法是什么?您只是无限期地尝试?顺序对于程序员来说是不可预测的,但是由于它是一个哈希映射,因此遵循“某种”算法,正确的测试应该尝试解决这个问题吗?
点击

2
请参阅__hash__。具体关于str类型。
metatoaster

根据定义,列表总是按照其表示方式进行排序。 这对我来说是一个关键声明。我决定只使用基本的2元组列表,OrderedDict这样就不会产生将列表转换为的开销OrderedDict。我只是遍历像列表这样的元素,而不是字典。
波博特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.