python: iterate over dictionary sorted by key

PythonSortingDictionary

Python Problem Overview


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.

Python Solutions


Solution 1 - Python

> 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

Solution 2 - Python

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

Solution 3 - Python

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.

Solution 4 - Python

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

Solution 5 - Python

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

Solution 6 - Python

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser984003View Question on Stackoverflow
Solution 1 - PythonDmitry ZagorulkinView Answer on Stackoverflow
Solution 2 - PythonAshwini ChaudharyView Answer on Stackoverflow
Solution 3 - PythonGrantJView Answer on Stackoverflow
Solution 4 - PythonDavid SchumannView Answer on Stackoverflow
Solution 5 - PythonAngelosView Answer on Stackoverflow
Solution 6 - PythonAchimView Answer on Stackoverflow