What is the most pythonic way to iterate over OrderedDict

Question:

I have an OrderedDict and in a loop I want to get index, key and value.
It’s sure can be done in multiple ways, i.e.

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

But I would like to avoid range(len(a)) and shorten a.iterkeys(), a.itervalues() to something like a.iteritems().
With enumerate and iteritems it’s possible to rephrase as

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

But it requires to unpack inside the loop body.
Is there a way to unpack in a for statement or maybe a more elegant way to iterate?

Asked By: Askold Ilvento

||

Answers:

You can use tuple unpacking in for statement:

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

Side Note:

In Python 3.x, use dict.items() which returns an iterable dictionary view.

>>> for i, (key, value) in enumerate(d.items()):
...     print(i, key, value)
Answered By: falsetru
$ 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

Is ugly, if you ask me.

I don’t know why are you interested in the index.
The idea between dict is that you are to be ignorant of the index.
There is a whole lot of logic behind dict and queues so that we are to be free of indexes.

If you insist in getting the index there is no need to iterate twice.

Let’s see what enumerate does to lists:

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

Note the “start”.

Enumerate knows how to manage lists. Dictionaries store data as a list, somewhere in the belly of the beast. So what happens if we use enumerate on a dict?

>>> for i,k in enumerate(a):
...    print i,k
... 
0 a
1 b

In this light I would go for the elegant:

>>> for i,k in enumerate(a):
...    print i,k,a[k]
... 
0 a 1
1 b 2

I feel that “for i, (k,v) in” exposes too much of the inner structure too soon.
With “for i,k in” we are protected and when times comes to refactor, we don’t need to touch the way we loop. We need to change only what we do in the loop. One less aspect to take care of.

Not to mention that this call to enumerate works just the same in any python after 2.6 🙂

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

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

Answered By: Andrei

Use the methods values or items to get a view and then typeset it as an iterator:

e.g. to sort by the values in your dictionary

sorted(iter(my_dict.values()))
Answered By: SumNeuron