Reputation: 1510
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?
Upvotes: 33
Views: 20952
Reputation: 5198
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()))
Upvotes: 0
Reputation: 369304
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)
Upvotes: 60
Reputation: 352
$ 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
Upvotes: 2