2012-10-08 46 views
0

假設我有一個如下所示的字典,其中值是每個鍵在文本中顯示的概率。Python:Range()作爲字典值

dict = {'a':0.66,'b':0.07,'c':0.04 and so on so the values of the dict sum up to one} 

說,我想建立另一個字典,這些值的範圍有價值。 由於我們不能使用range()和float,所以我試圖先將所有值乘以100,然後它們變成int。 假設我們想用它們的範圍替換這些值。因此,例如'a'將得到一個範圍(0,66),'b'範圍(66,73),'c'(73,77)等。 我試圖用下面的循環做到這一點,但它不' t工作:

start = 0 
end = 0 
for k,v in dict.items(): 
    end+=int(v*100) 
    range_dict[k]=range(start,end) 
    start+=end 

有人可以幫我嗎?我很想搞清楚該怎麼做!

+3

你試圖實現加權隨機算法,對不對? – satoru

+0

@ Satoru.Logic是 – user1718064

+2

在最後一行,它應該是'開始=結束'而不是'開始+ =結束' – yakxxx

回答

3

如果更改

start += end 

start = end 

它應該工作(使用xrange這裏以使其更可見):

>>> d = {'a':0.66,'b':0.07,'c':0.04} 
>>> start = 0 
>>> end = 0 
>>> range_dict = {} 
>>> for k,v in d.items(): 
... end+=int(v*100) 
... range_dict[k]=xrange(start,end) 
... start=end 
... 
>>> range_dict 
{'a': xrange(66), 'c': xrange(66, 70), 'b': xrange(70, 77)} 

但如果作爲@ Satoru.Logic猜測你想要一個加權的隨機數,有更好的方法。 Eli Bendersky對Python here中的方法有很好的概述。

+1

FWIW你沒有提到_why_從開始+ =結束到'開始=結束'是一個變化,所以請允許我。這是因爲,正確的說,前者需要「開始+ =結束開始」,這當然會降低到後者。 – martineau

+0

喜歡使用xrange(清楚地說明)和Eli Bendersky頁面的鏈接對我來說非常有用。謝謝。 –

0

被盜自豪地從Python 3.3.0文檔:

random - 9.6.2. Examples and Recipes - 包含加權分配算法。
itertools.accumulate - 包含累加算法。

下面的代碼是爲2.X寫:

import random 
import bisect 

D = {'a':0.66,'b':0.07,'c':0.04,'d':0.20,'e':0.03} 

# This function is in Python 3.2+ itertools module. 
def accumulate(iterable): 
    'Return running totals' 
    # accumulate([1,2,3,4,5]) --> 1 3 6 10 15 
    it = iter(iterable) 
    total = next(it) 
    yield total 
    for element in it: 
     total = total + element 
     yield total 

# Extract the weights and build a cumulative distribution. 
choices, weights = zip(*D.items()) 
cumdist = list(accumulate(weights)) 

# Make 1000 random selections 
L = [choices[bisect.bisect(cumdist, random.random() * cumdist[-1])] 
    for _ in xrange(1000)] 

# Display the results 
for c in sorted(D.keys()): 
    print '{} {:3d}'.format(c,L.count(c)) 

輸出:

a 652 
b 72 
c 43 
d 200 
e 33