7

I'd like to iterate on an OrderedDict in reverse order.

I.e. reverse the order of:

for k, v in my_ordered_dict.iteritems():
   # < do stuff >

So far I've gotten a non-lazy version, by reversing a list:

for k, v in list(my_ordered_dict.iteritems())[::-1]:
   # < do stuff >

Any ideas how to make it better?

martineau
  • 119,623
  • 25
  • 170
  • 301
Yuval Atzmon
  • 5,645
  • 3
  • 41
  • 74

2 Answers2

14

If you use reversed on the dict it should evaluate lazily:

for k, v in ((k, my_ordered_dict[k]) for k in reversed(my_ordered_dict)):
    .....

How does this work?

The key element here is a generator expression, which is evaluated lazily. So this will lazily evaluate over the keys of the ordered dict, and then return a tuple of the key and the dict value when needed.

I only need to support python 3:

In python 3, dict.items() is now a view and is evaluated lazily. Thus the above can be simplified to:

for k, v in reversed(my_ordered_dict.items()):

While Python 2.7 does have a viewitems() method, Python 2.7 OrderedDict views do not support the __reversed__ hook that reversed needs to reverse non-sequences.

user2357112
  • 260,549
  • 28
  • 431
  • 505
Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
  • 1
    could you simplify this further to `for k, v in reversed(my_ordered_dict.items()):` ? – maxymoo Mar 20 '17 at 05:13
  • And why wouldn't `for k, v in reversed(my_ordered_dict.iteritems())` work for Py2? – AChampion Mar 20 '17 at 05:52
  • @AChampion: `reversed` doesn't accept iterators. (`viewitems` won't work either, because Python 2 OrderedDict views don't support `__reversed__`.) – user2357112 Mar 20 '17 at 18:23
  • Good point. Then `for k in reversed(my_ordered_dict): v = my_ordered_dict[k] ...`, as `OrderedDict` does have `__reversed__()` Py2. – AChampion Mar 20 '17 at 20:55
-2

You could for in range with the values and then subtract from the number of values.

items = my_ordered_dict.iteritems()
max_index = len(items)

for i in range(max_index):
    object = items[max_index - i - 1]
meyer9
  • 1,120
  • 9
  • 26
  • 1
    In Python 2.7—which it looks like you're using—`max_index = len(items)` -> `TypeError: object of type 'generator' has no len()`. In Python 3, using `my_ordered_dict.items()` results in `TypeError: 'odict_items' object does not support indexing` for the line `object = items[max_index - i - 1]`. – martineau Dec 31 '18 at 01:22