以概率添加元素到数组

时间:2017-04-13 01:07:46

标签: python arrays list python-3.x random

所以我在Python中构建一个列表,例如,让我们说前100个整数,但我确实需要所有100个整数,但只有一个样本可以说3个。

import random 

def f():
    list_ = []
    for i in range(100):
        list_.append(i)
    return list_

def g(list_,k):
     return random.sample(list_, k)

print(g(f(),3))

>>>[50, 92, 6]

现在我可以逃避不首先构建整个列表,但直接构建样本,可能是通过添加一个概率,将元素添加到f()

中的列表中

因为如果我构建的是一个庞大的列表,它不是整数而是一些其他对象,那么就内存和计算而言,这种方法可能成本很高。

1 个答案:

答案 0 :(得分:3)

def random_no_dups_k_of_n(k, n):
    res = list(range(k))
    for i in range(k, n):
        v = random.randint(0, i) # this is 0-i inclusive
        if v == i:
            ir = random.randint(0,k-1)
            res[ir] = i
    return res

这里发生了什么:它是一种伸缩产品。从0k-1的每个元素开始都有k/k被选中的机会。第一次迭代后k1/(k+1)次被选中的机会,而所有其他人(不仅仅是剩下的,但全部)都有(k-1)/k * k/(k+1) = (k-1)/(k+1)次被选中的机会。第二次迭代后,k+11/(k+2)次被选中的机会,而其他所有人都有(k-1)/(k+1) * (k+1)/(k+2) = (k-1)/(k+2)次被选中的机会。等等。最后,每个号码都有k/n次被选中的机会。

实际上,我刚看到你可以做random.sample(range(n), k)。我只是假设它不可用。

编辑 :我得到了上面颠倒的概率。正确的版本应该是:

def random_no_dups_k_of_n(k, n):
    res = list(range(k))
    for i in range(k, n):
        v = random.randint(0, i) # this is 0-i inclusive
        if v < k:
            ir = random.randint(0,k-1)
            res[ir] = i
    return res

0k-1的每个元素开始都有k/k被选中的机会。第一次迭代后kk/(k+1)次被选中的机会,而所有其他人(不仅仅是剩下的,但全部)都有k/k*((k-1)/k * k/(k+1) + 1(k+1) = k/(k+1)次被选中的机会。第二次迭代后,k+1k/(k+2)的机会被选中,而其他所有人都有k/(k+1)*((k-1)/k * k/(k+2) + 2/(k+2))= k/(k+2)次被选中的机会。

这实际上会折叠所有计算,以便在k/(k+m)步之后为每个元素提供m个机会。