2012-02-13 13 views
4

私のリストは約です。 10000アイテム。現在の状況では、すべてのアイテムに関連する重み(優先度または重要度)があります。最小の重みは-100(負の値とゼロの値は削除可能)で、最高の重みは1500です。体重は人々の直感によって決定されます(どのように項目がコミュニティにとって重要であると思うか)。最も重要なアイテムを決定することは容易ではないので、ランダムな要素を使用したいので、重みの低いアイテムが選択され、将来の重さが調整されます(常識とランダム性)。ランダムなアイテムを選択してください。

関数をコード化する方法を知っていますか?getItem

def getItem(dict): 
    # this function should return random item from 
    # the dictionary of item-weight pairs (or list of tuples) 
    # Normally I would return only random item from the dictionary, 
    # but now I'd like to have this: The item with weight 1500 should 
    # have much more chance to be returned than the item with weight 10. 
    # What's my idea is to sum up the weights of all items and then compute 
    # some ratios. But maybe you have better idea. 
    return randomItem 

データベースにデータを格納している場合は、SQLを使用することができますあなたの

+1

こんにちは、私は最近、そのような質問に答えました:http://stackoverflow.com/a/9073313/862629 –

答えて

11

はこれを見て持って、私はそれはあなたが示唆した最も簡単な方法がある

Weighted random generation in Python異なる方法の間でいくつかの素晴らしい比較ですと必要なものだと思う:あなたはより詳細な情報を見つけることができます

import random 

def weighted_choice(weights): 
    totals = [] 
    running_total = 0 

    for w in weights: 
     running_total += w 
     totals.append(running_total) 

    rnd = random.random() * running_total 
    for i, total in enumerate(totals): 
     if rnd < total: 
      return i 

と可能性のある改善だけでなく、上記のリンクのいくつかの異なるアプローチ。

+0

[SOに関する回答は自己完結型でなければなりません](http://meta.stackexchange.com/questions/18669/should-posts-be-self-contained)ので、リンクされた記事の本質をあなたの答えに取り入れることを検討してください。 –

-2

ありがとう:

SELECT * FROM table ORDER BY weight*random() DESC LIMIT 1 
+1

誰がSQLについて何を言ったのですか? –

+0

きちんとしていますが、それはSQLで、質問にはpythonタグが付いています。とにかく、私はそのアイデアが好きです。 –

+0

どのように私は 'データベースを使用している場合' ... – coppettim

0

重みが負でない場合、それが行う方が簡単です。負の重みを持たなければならない場合は、最小の重みで重みを相殺する必要があります。あなたのケースでは、擬似コードでoffsetted_weight = itemweight + 100

が、それはこのように書きます:

Calculate the sum of all the weights. 
Do a random from 0 to the sum of the weights 
Set i to 0 
While the random number > 0 
    Subtract the weight of the item at index i from random 
    If the random number is < 0 return item[i] 
    Add 1 to i 
+0

負の重みは、すべての項目の重みが1になってから最初に現れました。ただし、負の重みを持つ必要はありません。負の値を取り除くことができます。 – xralf

3

あなたは0と(定義によって正)の重みの合計の間の乱数を抽出する必要があります。次に、bisect:http://docs.python.org/library/bisect.html(bisect標準モジューク)を使ってリストから項目を取得します。

import random 
import bisect 
weight = {'a':0.3,'b':3.2,'c':2.4} 
items = weight.keys() 
mysum = 0 
breakpoints = [] 
for i in items: 
    mysum += weight[i] 
    breakpoints.append(mysum) 

def getitem(breakpoints,items): 
    score = random.random() * breakpoints[-1] 
    i = bisect.bisect(breakpoints, score) 
    return items[i] 

print getitem(breakpoints,items)