Python OrderedDict 迭代

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16553506/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 22:59:05  来源:igfitidea点击:

Python OrderedDict iteration

pythonordereddictionary

提问by neil.millikin

Why does my python OrderedDict get initialized 'out of order'?

为什么我的 python OrderedDict 被初始化为“乱序”?

The solution here is less intriguing than the explanation. There's something here I just don't get, and perhaps an expanation would help others as well as me.

这里的解决方案没有解释那么有趣。这里有一些我不明白的东西,也许扩展会帮助其他人和我一样。

>>> from collections import OrderedDict

>>> spam = OrderedDict(s = (1, 2), p = (3, 4), a = (5, 6), m = (7, 8))

>>> spam
OrderedDict([('a', (5, 6)), ('p', (3, 4)), ('s', (1, 2)), ('m', (7, 8))])

>>> for key in spam.keys():
...    print key    
...
#  this is 'ordered' but not the order I wanted....
a
p
s
m

# I was expecting (and wanting):
s
p
a
m

采纳答案by Chris Krycho

From the docs:

文档

The OrderedDict constructor and update()method both accept keyword arguments, but their order is lost because Python's function call semantics pass-in keyword arguments using a regular unordered dictionary.

OrderedDict 构造函数和update()方法都接受关键字参数,但它们的顺序丢失了,因为 Python 的函数调用语义使用常规无序字典传入关键字参数。

So initialization loses the ordering, because it's basically calling a constructor with **kwargs.

所以初始化失去了顺序,因为它基本上是用**kwargs.

Edit:In terms of a solution(not just an explanation)—as pointed out in a comment by the OP, passing in a single list of tuples willwork:

编辑:解决方案而言(不仅仅是解释)——正如OP 在评论中指出的那样,传入单个元组列表起作用:

>>> from collections import OrderedDict
>>> spam = OrderedDict([('s',(1,2)),('p',(3,4)),('a',(5,6)),('m',(7,8))])
>>> for key in spam:
...     print(key)
...
s
p
a
m
>>> for key in spam.keys():
...     print(key)
...
s
p
a
m

This is because it's only getting a single argument, a list.

这是因为它只得到一个参数,一个列表。

回答by Paddy3118

@Chris Krycho gave a good explanation of why things fail.

@Chris Krycho 很好地解释了事情失败的原因。

If you look at the repr() of an OrderedDict you get a hint at how to impart order from the beginning: You need to use a list of (key, value) pairs to preserve the order of the keys given by the list.

如果您查看 OrderedDict 的 repr() ,您会得到如何从一开始就传递顺序的提示:您需要使用(键,值)对的列表来保留列表给出的键的顺序。

Here's one I did earlier:

这是我之前做的一个:

>>> from collections import OrderedDict
>>> spamher = OrderedDict(s=6, p=5, a=4, m=3, h=2, e=1, r=0)
>>> spamher
OrderedDict([('h', 2), ('m', 3), ('r', 0), ('s', 6), ('p', 5), ('a', 4), ('e', 1)])
>>> 
>>> list(spamher.keys())
['h', 'm', 'r', 's', 'p', 'a', 'e']
>>> 
>>> spamher = OrderedDict([('s', 6), ('p', 5), ('a', 4), ('m', 3), ('h', 2), ('e', 1), ('r', 0)])
>>> list(spamher.keys())
['s', 'p', 'a', 'm', 'h', 'e', 'r']
>>> 

(It just so happened that in Python v3.3.0 your original example of spamkept the keys in their original order from the outset. I changed to spamherto get arounf this).

(碰巧的是,在 Python v3.3.0 中,您的原始示例spam从一开始就将键保持在原始顺序中。我更改为spamher以解决此问题)。

回答by Cody Piersall

As the otheranswershave mentioned, trying to pass a dict to OrderedDict or using keyword arguments doesn't preserve the order. Passing in tuples is kinda ugly, though, and this is Python. It should be beautiful.

正如其他答案所提到的,尝试将 dict 传递给 OrderedDict 或使用关键字参数不会保留顺序。不过,传入元组有点难看,这就是 Python。它应该很漂亮。

You can abuse __getitem__on a class in order to have dict-like syntax for creating OrderedDict "literals":

你可以在一个类上使用ab 来使用__getitem__类似 dict 的语法来创建 OrderedDict “literals”:

from collections import OrderedDict
class OD(object):
    """This class provides a nice way to create OrderedDict "literals"."""
    def __getitem__(self, slices):
        if not isinstance(slices, tuple):
            slices = slices,
        return OrderedDict((slice.start, slice.stop) for slice in slices)
# Create a single instance; we don't ever need to refer to the class.
OD = OD()

Now you can use dict-like syntax to create an OrderedDict:

现在您可以使用类似 dict 的语法来创建 OrderedDict:

spam = OD['s': (1, 2), 
          'p': (3, 4), 
          'a': (5, 6), 
          'm': (7, 8)]
assert(''.join(spam.keys()) == 'spam')

This works because inside the square brackets, Python creates sliceliterals, which happen to look like dict syntax if you squint a little.

这是有效的,因为在方括号内,Python 创建了切片文字,如果你斜眼看,它恰好看起来像 dict 语法。

The ODclass could benefit from error checking, but this demonstrates how it can work.

OD班可受益于错误检查,但是这展示它如何能工作。