views:

266

answers:

4

I am trying to sort a dict based on its key and return an iterator to the values from within an overridden iter method in a class. Is there a nicer and more efficient way of doing this than creating a new list, inserting into the list as I sort through the keys?

+2  A: 

By far the easiest approach, and almost certainly the fastest, is something along the lines of:

def sorted_dict(d):
    keys = d.keys()
    keys.sort()
    for key in keys:
        yield d[key]

You can't sort without fetching all keys. Fetching all keys into a list and then sorting that list is the most efficient way to do that; list sorting is very fast, and fetching the keys list like that is as fast as it can be. You can then either create a new list of values or yield the values as the example does. Keep in mind that you can't modify the dict if you are iterating over it (the next iteration would fail) so if you want to modify the dict before you're done with the result of sorted_dict(), make it return a list.

Thomas Wouters
+8  A: 

How about something like this:

def itersorted(d):
    for key in sorted(d):
        yield d[key]
dF
sorted() actually makes an intermediate list.
Thomas Wouters
Thanks, edited to remove that...
dF
it would make more sense to yield key, d[key]
Moe
@Moe: I just did yield d[key] because the question asked for an "iterator to the values"
dF
A: 

Assuming you want a default sort order, you can used sorted(list) or list.sort(). If you want your own sort logic, Python lists support the ability to sort based on a function you pass in. For example, the following would be a way to sort numbers from least to greatest (the default behavior) using a function.

def compareTwo(a, b):
  if a > b:
    return 1
  if a == b:
    return 0
  if a < b:
    return -1

List.Sort(compareTwo)
print a

This approach is conceptually a bit cleaner than manually creating a new list and appending the new values and allows you to control the sort logic.

LJ
+2  A: 
def sortedDict(dictobj):
    return (value for key, value in sorted(dictobj.iteritems()))

This will create a single intermediate list, the 'sorted()' method returns a real list. But at least it's only one.

Jerub