如何创建一个随机整数列表,但排除特定的数字?

5

我想在Python中创建一个随机数字列表,但要排除某个数字k。

我可以创建一个整数的随机列表: l = [random.randint(0,10) for i in range(5)] 如果其中包含数字k,那么我可以将其删除,并添加一个新的范围内的随机数字,但这似乎需要太多步骤。

在研究中,发现如何从范围内创建一个随机数并排除某个数字是非常容易的,例如: print (choice([i for i in range(0,9) if i not in [2,5,7]])) 我可以按照需要创建数组的次数执行此操作,但这似乎比必要的更为复杂。

希望得到一些反馈。


如果你想要一个实际的解决方案,但理论上并不总是有效的:生成比你实际需要的随机数多_n_倍,然后进行过滤。 - L3viathan
5个回答

7

列出范围内的数字,并从列表中删除 k。然后,您可以使用 random.choices() 从列表中选择多个元素。

numbers = list(range(0, 11))
numbers.remove(k)
result = random.choices(numbers, k=5)

2
可以运行,但是根据您需要的数字范围和数量来看,这似乎有点浪费(例如 range(0, 1000000))。 - L3viathan
内存很便宜。但是请随意发布更好的解决方案。 - Barmar
我并不是说我的解决方案更好,对于从0到10的范围来说,这是一个很好的解决方案,或许也适用于0到1000。这只是需要记在心里的一些事情。 - L3viathan

3
你可以编写一个生成器,生成你选择的随机数,并取前n个:
def random_numbers_except(a, b, exclusions):
    while True:
        while (choice := random.randint(a, b)) in exclusions:
            pass
        yield choice

numbers = [number for _, number in zip(range(5), random_numbers_except(0, 10, [2, 5, 7]))

3

您还可以创建自己的生成器并在列表推导中使用它。

def my_random_generator(n_values, min_value, max_value, excluded_values=None):
    if excluded_values is None:
        excluded_values = []

    count = 0

    while count < n_values:
        value = random.randint(min_value, max_value)
        while value in excluded_values:
            value = random.randint(min_value, max_value)
        yield value
        count += 1


# Then
l = [_ for _ in my_random_generator(5, 0, 10, [2, 5, 7])]

# Or, (added after the discussion below)
l = list(my_random_generator(5, 0, 10, [2, 5, 7]))

在Python >= 3.8中,可以使用赋值运算符来使其更短。 - Trevis
为什么你在结尾使用了一个笨拙的列表推导式,而不是l = list(my_random_generator(5, 0, 10, [2, 5, 7])) - Mark Ransom
习惯的力量,我猜。至少对我来说不再尴尬了。现在理论上,我还不确定https://dev59.com/JVQK5IYBdhLWcg3wbfaW#51861670中的问题和答案是否适用于这里,但我认为是这样的。 - Trevis
这是一个有趣的链接,特别是因为不同的答案对于两个选项得出了相反的结论。除非在最关键的应用中,否则差异并不大,因此我会选择可读性更好的选项,我认为我的替代方案更易读。当然,你可能仍然持不同意见。 - Mark Ransom
感谢您的提问和讨论。我同意 list 更加直观,当然在这里也可以使用它。不过,我喜欢我的回答提供的学习机会,所以现在我还是坚持它。 - Trevis

1
你可以生成你需要的随机数范围并减去你想要排除的数量。每当选择到一个例外数字时,你可以将其映射到范围末尾。
这样说通了吗?如果不行,也许代码可以:
import random

random_range = range(0,1000)
exclude = [5, 55, 555]

def generate(n:int, ran: range, exclude:list):
    exclusive_range = range(ran.start, ran.stop-len(exclude))
    randoms = []
    for i in range(n):
        r = random.choice(exclusive_range)
        if r in exclude:
            r = exclusive_range.stop + exclude.index(r)
        randoms.append(r)
    return randoms

x = generate(1000, random_range, exclude)

在我的例子中,数字5将被映射到997,数字55将被映射到998,数字555将被映射到999。

0

你可以从一个比范围少一的范围中选择随机数,对于每个选定的数字,当它大于或等于 k 时,加1:

import random

k = 50  # number to exclude
n = 100  # range: choices should be in {0,...,49,51,...,99}
rnd = random.randrange(0, n - 1)  # in {0,...,98}
rnd += int(rnd >= k)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接