在Python中不使用最后n个值生成随机数

在Python中不使用最后n个值生成随机数,python,random,Python,Random,我有一个Python函数,它生成一个介于0和100之间的随机数: def get_next_number(): value = randint(0,100) 每次调用此函数时,我都需要它返回一个随机数,但该数不能是它返回的最后n个随机数之一(本例中假设为5) 以下是一些例子: 55、1、67、12、88、91、100、54(这很好,因为返回的最后5个数字没有重复) 77,42,2,3,88,2。。。(当函数得到一个随机数2时,我需要它再试一次,因为2之前已经返回了3个数字) 89,23

我有一个Python函数,它生成一个介于0和100之间的随机数:

def get_next_number():
    value = randint(0,100)
每次调用此函数时,我都需要它返回一个随机数,但该数不能是它返回的最后n个随机数之一(本例中假设为5)

以下是一些例子:

55、1、67、12、88、91、100、54(这很好,因为返回的最后5个数字没有重复)

77,42,2,3,88,2。。。(当函数得到一个随机数2时,我需要它再试一次,因为2之前已经返回了3个数字)

89,23,29,81,99100,6,8,23。。。(这一次没有问题,因为23次之前发生了5次以上)

随机函数中有什么东西可以实现这一点吗?

反过来想想

与生成随机数然后检查之前是否已生成该随机数不同,您可以首先生成非重复数集,以便逐个拾取,从而消除生成重复数的可能性

您还需要跟踪生成的最后5个项目,以便将它们从拾取的项目中排除

这样做可以:

s = set(range(0, 100))
last5 = []
def get_next_number():
    reduced_list = list(s - set(last5))
    i = randint(0, len(reduced_list) - 1)
    last5.append(reduced_list[i])
    if len(last5) > 5:
        last5.pop(0)
    return reduced_list[i]
要测试:

result = []
for i in range(0, 5000):
    result.append(get_next_number())
print(result)

逐步解释:

  • 生成要拾取的数字集(例如,0到99),并生成空列表以存储最后5个拾取的数字:

    s = set(range(0, 100))
    last5 = []
    
  • 在该方法中,从被拾取的可能性中排除最后5个拾取的数字:

    reduced_list = list(s - set(last5))
    
  • 缩减列表
    中选择随机数,保留在
    缩减列表
    中的所有数字均有效。将编号追加到
    last5
    列表中

    i = randint(0, len(reduced_list) - 1) #get any valid index. -1 is needed because randint upperbound is inclusive
    last5.append(reduced_list[i]) #the number is as what it pointed by the index: reduced_list[i], append that number to the last 5 list
    
  • 检查
    last5
    列表中是否已有成员>5。如果是,您需要先删除其成员:

    if len(last5) > 5:
        last5.pop(0)
    
  • 返回您选择的成员:

    return reduced_list[i]
    

  • 为了实现这一点,可以使用迭代器。下面是该应用程序的示例代码:

    import random
    
    class UniqueRandom(object):
        def __init__(self, num):
            self.unused_nums = range(num)
            self.num = num
    
        def __iter__(self):
            return self
    
        def next(self):
            if self.num:
                random_num = random.randrange(self.num)
                unique_num = self.unused_nums[random_num]
                self.unused_nums[random_num], self.unused_nums[self.num-1] = self.unused_nums[self.num-1], self.unused_nums[random_num]
                self.num -= 1
                return unique_num
            else:
                raise StopIteration
    
    例如,要生成0到100之间的随机数:

    random_num = UniqueRandom(100)
    print next(random_num)  # 54
    print next(random_num)  # 33
    
    要刷新值,请创建新的迭代器对象:

    random_num = UniqueRandom(100)
    print next(random_num)  # 92
    print next(random_num)  # 33 (repeated)
    
    您也可以在列表中使用它:

    >>> for i in UniqueRandom(5):
    ...     print i
    ... 
    2
    1
    0
    3
    4
    

    你需要多少随机数

    使用Python的内置
    random.sample
    方法。它列出了从总体序列或集合中选择的唯一的元素,用于无需替换的随机抽样

    >>> import random
    >>> random.sample(range(1, 100), 3)
    [56, 43, 74]
    
    创建一个大的随机整数列表。然后,在需要时,
    pop()

    >>> rands = random.sample(range(1, 100), 20)
    >>> rands
    [63, 23, 68, 72, 18, 83, 56, 34, 19, 7, 51, 5, 89, 47, 26, 49, 2, 1, 93, 84]
    >>> rands.pop()
    84
    >>> rands.pop()
    93
    

    保存最后五个数字,并告诉程序在匹配时获取一个新的随机数。不确定这是否有效。当我去生成第12个数字时,它可能是最后使用的5个数字之一。@user1624184好的,我的答案已更新。请再次检查Hanks,这是有道理的,但我一直收到这个错误:last5.append(reduced_s[I])indexer:list index out of therange@user1624184对不起,忘记把
    -1
    放在那里了。。。更新。请试一试again@user1624184
    i=randint(0,len(精简列表)-1)#获取任何有效索引-1是必需的,因为randint上限是包含的
    我不需要每次都使用唯一的随机数。调用函数5次后,我希望随机数再次可用。在迭代器中使用上述逻辑,并在需要刷新迭代器函数中添加的值时调用新的迭代器对象。验证它,它正在工作。早些时候它有一些问题。刚刚更新了代码