Reputation: 133
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
Upvotes: 2
Views: 1999
Reputation: 8891
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
Upvotes: 2
Reputation: 55479
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.
Upvotes: 1
Reputation: 1411
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')])
Upvotes: 1
Reputation: 3355
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')]
Upvotes: 2
Reputation: 11553
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
Upvotes: 0
Reputation: 1840
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])))
Upvotes: 2
Reputation: 42758
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]))
Upvotes: 0