简体   繁体   中英

How to sort a dictionary in Python with keys of mixed letters and numbers?

I have a dictionary like this:

dict_str = {'Number_1_item':'foo',
            'Number_11_item':'bar',
            'Number_22_item':'foobar',
            'Number_5_item':'barfoo'}

And my desired out put is:

sorted_dict_str = {'Number_1_item':'foo',
            'Number_5_item':'bar',
            'Number_11_item':'foobar',
            'Number_22_item':'barfoo'}

So the sorted_dict_str is sorted in numerical way based on the keys in dict_str. I have found some answers to sort the keys with pure numeric keys but not mixed ones, so they are not really helpful.

Thanks a lot.

Regards

Yet another solution. When executing the sorted function it'll return a sorted list of all the keys in the dictionary. A dictionary can't be sorted (though there is a way of having an ordered dictionary ).

This Solution is also more robust compared to the first solution, since the number can be anywhere in the key.

import re
from collections import OrderedDict 

d = {'Number_1_item':'foo',
            'Number_11_item':'bar',
            'Number_22_item':'foobar',
            'Number_5_item':'barfoo'}

keys = d.keys()

def sort_mixed(key):
    int_match = re.search(r'(?P<int>\d+)', key)
    number = int_match.group(0)
    return int(number)

sorted_keys = sorted(keys, key=lambda key: sort_mixed(key))
print(sorted_keys) # print sorted keys

sorted_dict = OrderedDict((k, d[k]) for k in sorted_keys)
print(sorted_dict)  # print new sorted dict

You can get sorted dict from your dict like that:

from collections import OrderedDict

OrderedDict(sorted(dict_str.items(), key=lambda s: int(s[0].split('_')[1])))

If we can assume that all the keys are on the format Number_XX_item , you could simply sort on the numeric part, using a lambda:

sorted_dict_str = sorted(dict_str.items(), key=lambda x: int(x[0].split('_')[1]))

This gives the following output:

sorted_dict_str = 
[('Number_1_item', 'foo'), 
 ('Number_5_item', 'barfoo'), 
 ('Number_11_item', 'bar'), 
 ('Number_22_item', 'foobar')]

You should check out natsort . There are ways to do it by yourself, without importing extra modules, but I like is method.

>>> from collections import OrderedDict
>>> import natsort

>>> input_dict = {'Number_1_item':'foo', 'Number_11_item':'bar', 'Number_22_item':'foobar', 'Number_5_item':'barfoo'}

>>> OrderedDict(natsort.natsorted(input_dict.items()))

OrderedDict([('Number_1_item', 'foo'), ('Number_5_item', 'barfoo'), ('Number_11_item', 'bar'), ('Number_22_item', 'foobar')])

Here's a solution using the slicing technique I mentioned in the comments. This is less robust than using .split , since the lengths of the prefix & suffix strings are hard-coded, but it's slightly faster because slicing is fast compared to a method call.

from collections import OrderedDict
from pprint import pprint

dict_str = {
    'Number_1_item':'foo',
    'Number_11_item':'bar',
    'Number_22_item':'foobar',
    'Number_5_item':'barfoo',
}

skeys = sorted(dict_str.keys(), key=lambda s: int(s[7:][:-5]))
sorted_dict = OrderedDict((k, dict_str[k]) for k in skeys)
pprint(sorted_dict)

output

OrderedDict([('Number_1_item', 'foo'),
             ('Number_5_item', 'barfoo'),
             ('Number_11_item', 'bar'),
             ('Number_22_item', 'foobar')])

You could also do the sorting on the (key, value) pairs inside the OrderedDict constructor call:

sorted_dict = OrderedDict(sorted(dict_str.items(), key=lambda u: int(u[0][7:][:-5])))

but I think my previous version is a little more readable.

You can't sort the dict itself by definition of what a dict is. But you can sort its keys in any custom order by passing the desired 'key' argument into sorted function

sorted(iterable[, cmp[, key[, reverse]]])

https://docs.python.org/2/library/functions.html#sorted

You can sort the keys of a dictionary into a list, with the additional key-Argument:

dict_str = {'Number_1_item':'foo',
            'Number_11_item':'bar',
            'Number_22_item':'foobar',
            'Number_5_item':'barfoo'}
sorted_keys = sorted(dict_str, key=lambda x: int(x.split('_')[1]))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM