-6

I have a dictionary with name dic in python, where the keys are strings and the corresponding values are integers.

dic ={ 'a' : 2, 'b' : 3, 'c':4, 'd':5 }.

Note that 2+3+4+5=14.

Now I need to impose an order to this dictionary, say the order is from 'a', to 'b', and then to 'c'. Then, I randomly generate 3 numbers from the list of intergers from 1 to 14, say, 2, 9, and 10. Then, these 3 numbers would correspond to the keys 'a', 'c', and 'd'.

All I can think of is to use dic.keys and dic.values to create two corresponding lists and then calculate the presums and do it in a very trivial way.

Is there a default python function to do this?

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
highsky
  • 125
  • 3
  • 11
  • 1
    Please show us what you have got so far. – fuesika Jun 04 '15 at 20:45
  • 1
    Why would `2`, `9`, and `10` correspond to `'a'`, `'c'`, and `'d'`? Was that arbitrarily chosen? – TigerhawkT3 Jun 04 '15 at 20:46
  • 1
    are you trying to randomly sample the keys with the given probabilities `(n/sum(...))`? – Jörn Hees Jun 04 '15 at 20:47
  • @TigerhawkT3: they happen to match to the cumulative sum of the values for those keys. – Martijn Pieters Jun 04 '15 at 20:48
  • 2
    Sounds like you are trying to make a [weighted random choice](http://stackoverflow.com/questions/3679694/a-weighted-version-of-random-choice), with the keys being the available choices and the values the weights.. – Martijn Pieters Jun 04 '15 at 20:49
  • No. Of course not. Imagine 'a' repeat for 2 times, 'b' repeats for 3 times, 'c' repeats for 4 times and 'd' repeats for 5 times. Now, put all these 4 types of strings in a box, and do a random sample of it. And I want to know how many differnt types of strings you have got. Sorry for the confusion. – highsky Jun 04 '15 at 20:50
  • @Martijin, yes, you are right. – highsky Jun 04 '15 at 20:51

1 Answers1

1

Maybe you can consider using random.sample like so.

>>> import random
>>> p = 2*['a'] + 3*['b'] + 4*['c'] + 5*['d']
>>> random.sample(p, 3)
['b', 'b', 'a']

From the docs, random.sample returns a k length list of unique elements chosen from the population sequence or set. It is used for random sampling without replacement. Therefore, the largest sample you can get from a population of size 14 is size 14, and a sample of size 14 is guaranteed to be a permutation of p.

Alternatively you can use your method of selecting an integer between 1 and 14 inclusive to make weighted random choices using p like this:

>>> k = random.choice(range(1, 15))
>>> p[k-1]
'b'

or, if you don't need the "index" of the selected element:

>>> random.choice(p)
'c'

However, note that by using random.choice repeatedly, you will be sampling with replacement (unless you have some mechanism of removing selecting elements from the population). This may be what you want though.

To construct your population p dynamically using your dictionary, you can do something like this:

>>> sum((w*[k] for k, w in dic.items()), [])
['d', 'd', 'd', 'd', 'd', 'a', 'a', 'c', 'c', 'c', 'c', 'b', 'b', 'b']

Note that the letters will not necessarily be in order as shown above! But anyways, you can sort them easily using Python's built in sorted function.

>>> sum(sorted(w*[k] for k, w in dic.items()), [])
['a', 'a', 'b', 'b', 'b', 'c', 'c', 'c', 'c', 'd', 'd', 'd', 'd', 'd']
Shashank
  • 13,713
  • 5
  • 37
  • 63