Reputation: 634
I would like to sort a dict based on keys that have a pattern like "[0-9]+_[A-Z]+". I would like it to be ordered by ascending number.
Here is where I am for the moment :
import operator
myDict = {
'120_str' : 'value',
'150_str' : 'value',
'110_str' : 'value',
'80_str' : 'value',
'10_str' : 'value',
'20_str' : 'value'
}
sortedDict = sorted(myDict.items(), key=operator.itemgetter(0))
What I actually have :
sortedDict = {
'10_str' : 'value',
'110_str' : 'value',
'120_str' : 'value',
'150_str' : 'value',
'20_str' : 'value',
'80_str' : 'value'
}
What I would like to have :
sortedDict = {
'10_str' : 'value',
'20_str' : 'value',
'80_str' : 'value',
'110_str' : 'value',
'120_str' : 'value',
'150_str' : 'value'
}
Upvotes: 1
Views: 64
Reputation: 1162
how about this? you can filter digits from the string and sort your dictionary based on that.
this also doesn't require you to split using a particular character. just in case if your key structure changes this would still work.
sorted(myDict.items(), key=lambda t: int(filter(str.isdigit, t[0])))
Upvotes: 2
Reputation: 164693
Here is one way, assuming output is a list of tuples. Dictionaries are not considered to be ordered, although they may be in the future.
Sort after converting to int
, then add back the string formatting:
myLst = [(str(k)+'_str', v) for k, v in \
sorted([(int(k.split('_')[0]), v) for k, v in myDict.items()])]
# [('10_str', 'value'),
# ('20_str', 'value'),
# ('80_str', 'value'),
# ('110_str', 'value'),
# ('120_str', 'value'),
# ('150_str', 'value')]
Upvotes: 1
Reputation: 71451
You can try this:
import re
sortedDict = {
'10_str' : 'value',
'110_str' : 'value',
'120_str' : 'value',
'150_str' : 'value',
'20_str' : 'value',
'80_str' : 'value'
}
final_data = sorted(sortedDict.items(), key=lambda x:int(re.findall('^\d+', x[0])[0]))
Output:
[('10_str', 'value'), ('20_str', 'value'), ('80_str', 'value'), ('110_str', 'value'), ('120_str', 'value'), ('150_str', 'value')]
Upvotes: 1
Reputation: 362786
>>> def key(s):
... n, s = s.split('_', 1)
... return int(n), s
...
>>> from collections import OrderedDict
>>> OrderedDict([(k, myDict[k]) for k in sorted(myDict, key=key)])
OrderedDict([('10_str', 'value'),
('20_str', 'value'),
('80_str', 'value'),
('110_str', 'value'),
('120_str', 'value'),
('150_str', 'value')])
Upvotes: 3
Reputation: 42017
Use _
separated first element (int
) as the sorting key:
sorted(myDict.items(), key=lambda x: int(x[0].split('_')[0]))
Use collections.OrderedDict
to maintain the ordering:
collections.OrderedDict(sorted(myDict.items(), key=lambda x: int(x[0].split('_')[0])))
Example:
In [109]: sorted(myDict.items(), key=lambda x: int(x[0].split('_')[0]))
Out[109]:
[('10_str', 'value'),
('20_str', 'value'),
('80_str', 'value'),
('110_str', 'value'),
('120_str', 'value'),
('150_str', 'value')]
In [110]: collections.OrderedDict(sorted(myDict.items(), key=lambda x: int(x[0].split('_')[0])))
Out[110]:
OrderedDict([('10_str', 'value'),
('20_str', 'value'),
('80_str', 'value'),
('110_str', 'value'),
('120_str', 'value'),
('150_str', 'value')])
Upvotes: 3