python: iterate over dictionary sorted by key

Each Answer to this Q is separated by one/two green lines.

I have a Python dictionary

steps = {1:"value1", 5:"value2", 2:"value3"}

I need to iterate over this sorted by key.

I tried this:

x = sorted(steps, key=lambda key: steps[key])

but the values are gone from x.

I need to iterate over this is sorted order by the key.

I think lambdas is overkill here, try this:

>>> steps = {1:"val1", 5:"val2", 2:"val3"}
>>>
>>> for key in sorted(steps):
...     print steps[key]
...
val1
val3
val2

You need to iterate over steps.items(), because an iteration over dict only returns its keys.

>>> x = sorted(steps.items())
>>> x
[(1, 'value1'), (2, 'value3'), (5, 'value2')]

Iterate over sorted keys:

>>> for key in sorted(steps):
...     # use steps[keys] to get the value

You can also use one of Python’s many SortedDict container types. These types automatically maintain the dictionary sorted in key-order. Take a look at the sortedcontainers module which is pure-Python and fast-as-C-implementations. There’s a performance comparison that benchmarks several other implementations against each other.

In your case then, you’d use:

from sortedcontainers import SortedDict
steps = SortedDict({1:"value1", 5:"value2", 2:"value3"})

# Then iterate the items:

for key, value in steps.items():
    print key, value

# Or iterate the values:

for value in steps.values():
    print value

Iteration for keys/values/items works automatically by sorted key order.

In case your keys are not integers, but strings that should be parsed as integers:

steps = {'1':'value1', '10': 'value0', '5':'value2', '2':'value3'}

you can use something similar to your solution:

for key in sorted(steps, key=lambda key: int(key)):
    print(key, steps[key])

1
2
5
10

Like pointed by Zagorulkin Dmitry, you should not pass a lambda to the sorting function. The sorting function default behaviour is to act on the keys.

steps = {1:"val1", 5:"val2", 2:"val3"}

for key in sorted(steps):
   print steps[key]
...
val1
val3
val2

However, passing the lambda to the sorting function isn’t a better operation of small benefit (i.e. an ‘overkill’), but it is actually undesired. It makes the code less readable and it also slower, particularly if you are going to apply it to very large dictionaries or make the call multiple times. Other than making the sorting target more explicit in respect to the (key, value) pairs, there is no benefit to using it. The following timings show the performance hit you get when specifying a lambda.

steps = {randint(0, 100000): randint(0, 100000) for _ in range(100000) } # random dict

%%timeit 
sort_list = [value for _, value in sorted(steps.items(), key=lambda item: item[0])]
1 loops, best of 3: 241 ms per loop

%%timeit 
sort_list = [steps[k] for k in sorted(steps, key=lambda k: k)]
1 loops, best of 3: 196 ms per loop

%%timeit
sort_list = [ steps[key] for key in sorted(steps) ]
10 loops, best of 3: 106 ms per loop

Depending on your use case, it might be an option to hold an already ordered dictionary. See pythons OrderedDict for details. If you want to sort the keys as integer, you have to convert them to integers. The best moment to do so depends on your use case.


The answers/resolutions are collected from stackoverflow, are licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0 .