tags:

views:

5850

answers:

5

There's an existing function that ends in:

return dict.iteritems()

that returns an unsorted iterator for a given dictionary. I would like to return an iterator that goes through the items in sorted order. How do I do that?

+12  A: 

Use the sorted() function:

return sorted(dict.iteritems())

If you want an actual iterator over the sorted results, since sorted() returns a list, use:

return iter(sorted(dict.iteritems()))
Greg Hewgill
That fails for me: <type 'exceptions.TypeError'>: iter() returned non-iterator of type 'list'
mike
That's probably because you use "dict" as the variable name. "dict" is actually the type name of dictionaries. Just use another name like "mydict" here and voila.
utku_karatas
Still not working. Are you positive sorted() returns another iterator, as opposed to a regular list?
mike
when and where does this exception occur? you can iterate over a list without a problem
hop
it could fail if you were calling the .next() method on the list, which would work on the iterator
Chris Cameron
well, i somehow took that problem as trivial ;)
hop
Agreed, hop. I don't think I ever call .next() directly except when skipping lines in files. Our iter(sorted(dict.iteritems())) solution ends up making a copy of the whole dict in memory at the "sorted(" stage anyway, so the primary iterator benefit seems lost :)
Chris Cameron
It needs to plug into an existing API that's expecting an iterator.
mike
+6  A: 

Greg's answer is right. Note that in Python 3.0 you'll have to do

sorted(dict.items())

as iteritems will be gone.

Claudiu
That fails for me: <type 'exceptions.TypeError'>: iter() returned non-iterator of type 'list'
mike
+4  A: 

A dict's keys are stored in a hashtable so that is their 'natural order', i.e. psuedo-random. Any other ordering is a concept of the consumer of the dict.

sorted() always returns a list, not a dict. If you pass it a dict.items() (which produces a list of tuples), it will return a list of tuples [(k1,v1), (k2,v2), ...] which can be used in a loop in a way very much like a dict, but it is not in anyway a dict!

foo = {
    'a':    1,
    'b':    2,
    'c':    3,
    }

print foo
>>> {'a': 1, 'c': 3, 'b': 2}

print foo.items()
>>> [('a', 1), ('c', 3), ('b', 2)]

print sorted(foo.items())
>>> [('a', 1), ('b', 2), ('c', 3)]

The following feels like a dict in a loop, but it's not, it's a list of tuples being unpacked into k,v:

for k,v in sorted(foo.items()):
    print k, v

Roughly equivalent to:

for k in sorted(foo.keys()):
    print k, foo[k]
Peter Rowell
Okay, but I don't want a Dict or a List, I want an Iterator. How do i coerce it into being an Iterator?
mike
+5  A: 

Haven't tested this very extensively, but works in Python 2.5.2.

>>> d = {"x":2, "h":15, "a":2222}
>>> it = iter(sorted(d.iteritems()))
>>> it.next()
('a', 2222)
>>> it.next()
('h', 15)
>>> it.next()
('x', 2)
>>>
Chris Cameron
A: 

sorted returns a list, hence your error when you try to iterate over it, but because you can't order a dict you will have to deal with a list.

I have no idea what the larger context of your code is, but you could try adding an iterator to the resulting list. like this maybe?:

return iter(sorted(dict.iteritems()))

of course you will be getting back tuples now because sorted turned your dict into a list of tuples

ex: say your dict was: {'a':1,'c':3,'b':2} sorted turns it into a list:

[('a',1),('b',2),('c',3)]

so when you actually iterate over the list you get back (in this example) a tuple composed of a string and an integer, but at least you will be able to iterate over it.

pcn