8

Let's say I have this dictionary:

dict = {'a': 100, 'b': 5, 'c': 150, 'd': 60};

I get the key which has greatest value with this code:

most_similar = max(dic.iteritems(), key=operator.itemgetter(1))[0]

it returns 'c'

But I want to select a random key from top 3 greatest values. According to this dictionary top 3 are:

c
a
d

It should randomly select a key from them. How can I do that?

gagan mahatma
  • 336
  • 2
  • 9
JayGatsby
  • 1,541
  • 6
  • 21
  • 41
  • 1
    So, you want a single random selection from a dictionary? Or a single random selection from a preexisting `list` of the top 3 keys? Or you want to find the top 3 keys, and then select a single random one from them? – TigerhawkT3 Jan 10 '16 at 15:40
  • 1
    I hate to be a downer, but this question is easily answered by combining the answers from [How do I randomly select an item from a list using Python?](http://stackoverflow.com/q/306400/1394393) and [5 maximum values in a python dictionary](http://stackoverflow.com/q/7197315/1394393). I've downvoted as a result, since that constitutes poor research effort in my book. Could you explain how this question distinguishes itself from just slapping those two together? – jpmc26 Jan 11 '16 at 03:02

3 Answers3

13

If you want to find the top 3 keys and then get one of the keys randomly, then I would recommend using random.choice and collections.Counter, like this

>>> d = {'a': 100, 'b': 5, 'c': 150, 'd': 60}
>>> from collections import Counter
>>> from random import choice
>>> choice(Counter(d).most_common(3))[0]
'c'

Counter(d).most_common(3) will get the top three values from the dictionary based on the values of the dictionary object passed to it and then we randomly pick one of the returned values and return only the key from it.

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • regarding your earlier comment on my answer: does `most_common` not have to do some sorting as well, such that the complexity is O(nlog(n)) for both solutions? – timgeb Jan 10 '16 at 15:49
  • What about [TigerhawkT3](http://stackoverflow.com/questions/34707280/selecting-random-values-from-dictionary/34707349#34707349)'s answer ? – Iron Fist Jan 10 '16 at 15:52
  • @IronFist That also has the same O(nlogn) complexity. – thefourtheye Jan 10 '16 at 15:53
  • 2
    For picking just 3 elements `most_common` should be closer to linear time http://stackoverflow.com/questions/29240807/python-collections-counter-most-common-complexity – Akavall Jan 10 '16 at 16:20
7

Get the keys with the three largest values.

>>> import heapq
>>> d = {'a': 100, 'b': 5, 'c': 150, 'd': 60}
>>> largest = heapq.nlargest(3, d, key=d.__getitem__)
>>> largest
['c', 'a', 'd']

Then select one of them randomly:

>>> import random
>>> random.choice(largest)
'c'
timgeb
  • 76,762
  • 20
  • 123
  • 145
4

Sort the dictionary by descending value, get the first three objects from the resulting list, then use random.choice:

>>> import random
>>> d = {'a': 100, 'b': 5, 'c': 150, 'd': 60}
>>> random.choice(sorted(d, reverse=True, key=d.get)[:3])
'c'

And don't call it dict or you'll mask the built-in.

timgeb
  • 76,762
  • 20
  • 123
  • 145
TigerhawkT3
  • 48,464
  • 6
  • 60
  • 97