在Python中,如何在范围内生成随机整数,排除列表中的某些数字?

2 投票
3 回答
2949 浏览
提问于 2025-04-18 03:08

比如说,一开始我想从0到9之间随机生成一个整数。

第一次,程序生成了2,然后我把2放进了“排除”列表。

下一次,我需要生成一个在0到9之间的数字,但要排除2。假设这是第二次,程序生成了5。

到了第三次,我需要生成一个在0到9之间的数字,同时要排除2和5。

因为这个范围非常大(有百万级别),有没有什么高效的方法呢?

3 个回答

0

你可以使用一个函数,这个函数可以把整数范围映射到同样的整数范围,但会有一些例外,像这样:

import random

def excection(val, exceptions):
    ''' Maps range of values into
        similar range of values with exceptions missing.
        Exceptions must be sorted increasingly.

        for excample with exceptions=(2, 5) it will map
        This:       0, 1, 2, 3, 4, 5, 6
        To this:    0, 1, 3, 4, 6, 7, 8
    '''
    if not exceptions:
        return val

    for e in exceptions:
        if val < e: 
            return val # value before any exclusion is unchanged
        val += 1 # after some exclusion value is larger by one

    return val


def randint_with_exceptions(min, max, exceptions):
    r = random.randint(min, max - len(exceptions)) # generate random number in range smaller then desired by number of exceptions
    return excection(r, exceptions) # and map it to desired, more sparse sequence

for i in range(20): # test possible randoms
    print randint_with_exceptions(0, 7, (2, 5)),

from functools import partial
ex_25 = partial(excection, exceptions=(2, 5))
assert ( # unittest sequence transformation
    map(ex_25, range(5))
    == [0, 1, 3, 4, 6]
)
4

根据random.sample的文档

如果你想从一系列整数中选择一些数字,可以使用xrange()这个对象作为参数。这种方法在从大量数据中抽样时特别快,而且占用空间少,比如你可以这样写:sample(xrange(10000000), 60)

这个方法是抽样不放回的,所以random.sample(xrange(n), k)会在范围[0, n)内给你k不同的数字(前提是k <= n)。

6

生成所有可能的值一次,然后把这些值打乱,每次从这个列表中取出一个值:

values = range(10)
random.shuffle(values)

def get_value():
    return values.pop()

这样最终会以随机的顺序产生范围内的所有值,而且不会重复。

撰写回答