【问题标题】:How do you create a random list of integers, but exclude a certain number?你如何创建一个随机的整数列表,但排除某个数字?
【发布时间】:2021-06-19 18:53:28
【问题描述】:

我想在 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 倍于您实际需要的随机数,然后进行过滤。

标签: python random


【解决方案1】:

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

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

【讨论】:

  • 有效,但是根据您需要的数字的范围和数量,这似乎有点浪费(例如range(0, 1000000)
  • 内存很便宜。但请随时发布更好的解决方案。
  • 我并不是说我的解决方案会更好,对于从 0 到 10 的范围,这是一个很好的解决方案,也许对于 0 到 1000 也是如此。这只是要记住的事情。
【解决方案2】:

您可以编写一个生成器,生成您选择的随机数,然后取第一个 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
    • 你为什么在结尾使用一个尴尬的列表推导而不是l = list(my_random_generator(5, 0, 10, [2, 5, 7]))
    • 我猜是习惯的力量。至少这对我来说不再尴尬了。现在理论上,我还不确定stackoverflow.com/a/51861670/9981846 的问题和答案是否适用于此,但我会这么说。
    • 这是一个有趣的链接,特别是因为不同的答案对这两个选项得出相反的结论。除了在最关键的应用程序中,差异还不够大,因此我会追求可读性,我认为我的替代方案更具可读性。当然,你可以继续不同意。
    • 感谢您的提问和讨论。我同意list 更直接,当然可以在这里使用。不过,我喜欢我的答案提供的学习机会,这就是我现在坚持下去的原因。
    【解决方案4】:

    您可以生成所需范围内的随机数,然后减去要排除的数字数量。只要选择卓越的号码,您可以将其映射到范围的末尾。

    这有意义吗?如果没有,也许代码可以:

    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。

    【讨论】:

      【解决方案5】:

      您可以从一个较短的范围中选择随机数,然后为每个单独的选择添加 1,当它大于或等于 k

      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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-13
        • 2015-07-02
        • 2018-11-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-12
        • 1970-01-01
        相关资源
        最近更新 更多