23

I have a dict (which is also a key of a larger dict) of dicts that looks like

wd[wc][dist][True]={'course': {'#': 1, 'Fisher': 4.0},
 'i': {'#': 1, 'Fisher': -0.2222222222222222},
 'of': {'#': 1, 'Fisher': 2.0},
 'will': {'#': 1, 'Fisher': 3.5}}

I want to sort the key words (at the highest level) by their corresponding 'Fisher' value... so that the output looks like

wd[wc][dist][True]={'course': {'Fisher': 4.0, '#': 1}, 'will': {'Fisher': 3.5, '#': 1}, 'of': {'Fisher': 2.0, '#': 1}, 'i': {'Fisher': -0.2222222222222222, '#': 1}}

I've tried working with items() and sorted() but can't work it out... Please help me out :(

ytrewq
  • 3,670
  • 9
  • 42
  • 71

2 Answers2

40

You can't sort a dict, but can get a sorted list of keys, values or (key,values) pairs.

>>> dic = {'i': {'Fisher': -0.2222222222222222, '#': 1}, 'of': {'Fisher': 2.0, '#': 1}, 'will': {'Fisher': 3.5, '#': 1}, 'course': {'Fisher': 4.0, '#': 1}}

>>> sorted(dic.items(), key=lambda x: x[1]['Fisher'], reverse=True)
[('course', {'Fisher': 4.0, '#': 1}),
 ('will', {'Fisher': 3.5, '#': 1}),
 ('of', {'Fisher': 2.0, '#': 1}),
 ('i', {'Fisher': -0.2222222222222222, '#': 1})
]

Or create an collections.OrderedDict(introduced in Python 2.7) after getting the sorted (key,value) pairs:

>>> from collections import OrderedDict
>>> od = OrderedDict(sorted(dic.items(), key=lambda x: x[1]['Fisher'], reverse=True))
>>> od
OrderedDict([
('course', {'Fisher': 4.0, '#': 1}),
('will', {'Fisher': 3.5, '#': 1}),
('of', {'Fisher': 2.0, '#': 1}),
('i', {'Fisher': -0.2222222222222222, '#': 1})
])

For your dictionary, try this:

>>> from collections import OrderedDict
>>> dic = wd[wc][dist][True]
>>> wd[wc][dist][True]= OrderedDict(sorted(dic.items(), key=lambda x: x[1]['Fisher'], reverse=True))
Ashwini Chaudhary
  • 244,495
  • 58
  • 464
  • 504
  • 1
    Note that [`OrderedDict`](http://docs.python.org/2/library/collections.html?highlight=ordereddict#ordereddict-examples-and-recipes) is only for Python versions 2.7 and above. – Burhan Khalid May 07 '13 at 06:36
  • using items() results in KeyError... why could that be? – ytrewq May 07 '13 at 06:38
  • @CosmicRabbitMediaInc One of your dictionaries may not have the `Fisher` key, is that correct? Try `all('Fisher' in d[k] for k in d)` and post output – jamylak May 07 '13 at 06:42
  • @jamylak Ive tried print dic.items() but it alone results in key error... is it still related to fisher key? btw my dic itself is also a key of a larger dic.. – ytrewq May 07 '13 at 06:44
  • @CosmicRabbitMediaInc This answer works fine, your data structure is not a dictionary – jamylak May 07 '13 at 06:45
  • @jamylak sorry I have a very clumsy understanding of dict and list... How could the answer be modified to fit my case? – ytrewq May 07 '13 at 06:46
  • 1
    @CosmicRabbitMediaInc Then try `larger_dict[key].items()`, or post the larger `dict` in question body. – Ashwini Chaudhary May 07 '13 at 06:46
  • @AshwiniChaudhary sorry for the confusion. I modified the question. Your new suggestion still results in key error... – ytrewq May 07 '13 at 06:48
  • @AshwiniChaudhary that worked magically. Thank you so much for saving me :) – ytrewq May 07 '13 at 06:59
5

If you just need the keys in order, you can get a list like this

dic = {'i': {'Fisher': -0.2222222222222222, '#': 1}, 'of': {'Fisher': 2.0, '#': 1}, 'will': {'Fisher': 3.5, '#': 1}, 'course': {'Fisher': 4.0, '#': 1}}
sorted(dic, key=lambda k: dic[k]['Fisher'])

if 'Fisher' might be missing, you can use this to move those entries last

sorted(dic, key=lambda x:dic[x].get('Fisher', float('inf')))

or '-inf' to place them at the beginning

John La Rooy
  • 295,403
  • 53
  • 369
  • 502