Python Dict中的随机值,最低值为优先级

时间:2013-12-10 17:18:05

标签: python random

在Google上找不到这个,所以如果有人可以提供帮助。我有这样的字典:

{8: 0, 5: 0, 6: 1, 4: 2, 7: 3, 9: 2, 11: 1, 10: 3}

现在我需要随机地从这个dict中取出3个键,这也是一个棘手的部分,在这样做时要考虑它们的价值。具体地说,我希望分配给它们的值较低的键具有较大的随机优先级,所以简而言之,如果有3个值为0/1的键,则不要给我一个值为2/3的键。现在我知道我可以按值排序并取3个最低值,但这是可以预测的,所以我需要任何类型的随机函数,同时采用最低的随机函数。 我希望我有一些道理......任何想法? 提前谢谢!

1 个答案:

答案 0 :(得分:1)

Select k random elements from a list whose elements have weightsHow can I make a random selection from an inversely-weighted list?结合并应用于您的词典:

import random
from operator import mul

class Node:
    __slots__ = ['w', 'v', 'tw']
    def __init__(self, w, v, tw):
        self.w, self.v, self.tw = w, v, tw

def rws_heap(items):
    h = [None]
    for w, v in items:
        h.append(Node(w, v, w))
    for i in range(len(h) - 1, 1, -1):
        h[i>>1].tw += h[i].tw
    return h

def rws_heap_pop(h):
    gas, i = h[1].tw * random.random(), 1
    while gas > h[i].w:
        gas -= h[i].w
        i <<= 1
        if gas > h[i].tw:
            gas -= h[i].tw
            i += 1
    w, v = h[i].w, h[i].v
    h[i].w = 0
    while i:
        h[i].tw -= w
        i >>= 1
    return v

def random_weighted_sample_no_replacement(items, n):
    heap = rws_heap(items)
    for i in range(n):
        yield rws_heap_pop(heap)

def random_weighted_sample_no_replacements_inverse_weights(mapping, n):
    keys, values = zip(*mapping.items())
    total = reduce(mul, (v + 1 for v in values))
    weights = (total / (v + 1) for v in values)
    heap = rws_heap(zip(weights, keys))
    for i in xrange(n):
        yield rws_heap_pop(heap)

我稍微压缩Jason's Python implementation,并通过使用乘法将所有权重反转(将所有权重向上移动1以允许除法技巧)。

将此应用到您的词典:

>>> list(random_weighted_sample_no_replacements_inverse_weights(d, 3))
[9, 11, 8]
>>> list(random_weighted_sample_no_replacements_inverse_weights(d, 3))
[8, 6, 9]
>>> list(random_weighted_sample_no_replacements_inverse_weights(d, 3))
[4, 8, 5]
>>> list(random_weighted_sample_no_replacements_inverse_weights(d, 3))
[4, 10, 11]
>>> list(random_weighted_sample_no_replacements_inverse_weights(d, 3))
[4, 9, 10]
>>> list(random_weighted_sample_no_replacements_inverse_weights(d, 3))
[5, 10, 8]
>>> list(random_weighted_sample_no_replacements_inverse_weights(d, 3))
[6, 4, 5]

其中85的显示频率高于711