如何最符合Python风格地迭代有序字典(OrderedDict)?

33

我有一个 OrderedDict ,在循环中我想得到索引、键和值。这可以用多种方式来实现,例如:

a = collections.OrderedDict({…})
for i,b,c in zip(range(len(a)), a.iterkeys(), a.itervalues()):
  …

但我想避免使用 range(len(a)),并将 a.iterkeys() 和 a.itervalues() 缩短为类似于 a.iteritems() 的形式。 通过使用 enumerate 和 iteritems,可以重述为

for i,d in enumerate(a.iteritems()):
  b,c = d

但是需要在循环体内部进行解包。是否有一种方法可以在for语句中进行解包,或者更加优雅地进行迭代?

3个回答

60

您可以在for语句中使用元组解包:

for i, (key, value) in enumerate(a.iteritems()):
    # Do something with i, key, value

>>> d = {'a': 'b'}
>>> for i, (key, value) in enumerate(d.iteritems()):
...     print i, key, value
... 
0 a b

小提示:

在Python 3.x中,请使用dict.items(),它返回一个可迭代的字典视图。

>>> for i, (key, value) in enumerate(d.items()):
...     print(i, key, value)

为什么您建议使用dict.items()呢?它会构造一个新的列表。 - omerfarukdogan
4
@farukdgn,在Python 3.x中,dict.items()返回一个视图而非列表。而且在Python 3.x中没有dict.iteritems。请参考字典视图 - falsetru

2
$ python
Python 2.6.6 (r266:84292, Nov 21 2013, 10:50:32) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux2
Type "help", "copyright", "credits" or "license" for more information. 
>>> import collections
>>> a = collections.OrderedDict({'a':'1','b':'2'})
>>> a
OrderedDict([('a', '1'), ('b', '2')])
>>> for i, (k,v) in enumerate(a.iteritems()):
...    print i, k, v
... 
0 a 1
1 b 2

很丑,如果你问我。
我不知道为什么你对索引感兴趣。 字典的想法是让我们忽略索引。 字典和队列背后有很多逻辑,使我们不必关注索引。
如果你坚持要获取索引,就没有必要迭代两次了。
让我们看看enumerate对列表做了什么:
>>> seasons = ['Spring', 'Summer', 'Fall', 'Winter']    
>>> list(enumerate(seasons))
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
>>> list(enumerate(seasons, start=1))
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]

注意“start”。 enumerate 知道如何管理列表。字典将数据存储为列表,某个地方在其内部。那么,如果我们在字典上使用 enumerate 会发生什么?
>>> for i,k in enumerate(a):
...    print i,k
... 
0 a
1 b

在这种情况下,我会选择优雅的方式:
>>> for i,k in enumerate(a):
...    print i,k,a[k]
... 
0 a 1
1 b 2

我认为“for i, (k,v) in”的写法暴露了太多的内部结构。使用“for i,k in”可以保护我们,在重构时,我们不需要改变循环的方式,只需要改变循环中所做的事情。少了一个需要关注的方面。
更不用说这个枚举函数在 Python 2.6 之后的任何版本中都能正常工作 :)

https://docs.python.org/2/library/stdtypes.html#dict.iteritems

https://docs.python.org/2/library/functions.html#enumerate


我需要一个索引来与一个知道顺序但不关心名称的组件进行接口。我试图减少[]的数量,因为对我来说它不仅仅是值的字典,而是对象的字典和一些对象是数组,每个[]都会在代码中带来痛苦。而且在某些时候,我已经将所有的iterkeys重构为iteritems,这样可以缩短代码。在这种情况下,使用字典列表可能更自然,但我更喜欢快速访问名称并保持与其他实体的统一性,这些实体是纯字典。 - Askold Ilvento
对我来说,字典列表比字典字典更可取,但这取决于您的特定情况。感觉你有一个上帝对象。 - Andrei

0
使用方法valuesitems获取一个view,然后将其设置为iterator
例如,按字典中的值进行排序。
sorted(iter(my_dict.values()))

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