Generating non-repeating random numbers in Python

前端 未结 17 1742
粉色の甜心
粉色の甜心 2020-11-30 19:56

Ok this is one of those trickier than it sounds questions so I\'m turning to stack overflow because I can\'t think of a good answer. Here is what I want: I need Python to ge

17条回答
  •  無奈伤痛
    2020-11-30 20:30

    I started trying to write an explanation of the approach used below, but just implementing it was easier and more accurate. This approach has the odd behavior that it gets faster the more numbers you've generated. But it works, and it doesn't require you to generate all the numbers in advance.

    As a simple optimization, you could easily make this class use a probabilistic algorithm (generate a random number, and if it's not in the set of used numbers add it to the set and return it) at first, keep track of the collision rate, and switch over to the deterministic approach used here once the collision rate gets bad.

    import random
    
    class NonRepeatingRandom(object):
    
        def __init__(self, maxvalue):
            self.maxvalue = maxvalue
            self.used = set()
    
        def next(self):
            if len(self.used) >= self.maxvalue:
                raise StopIteration
            r = random.randrange(0, self.maxvalue - len(self.used))
            result = 0
            for i in range(1, r+1):
                result += 1
                while result in self.used:
                     result += 1
            self.used.add(result)
            return result
    
        def __iter__(self):
            return self
    
        def __getitem__(self):
            raise NotImplemented
    
        def get_all(self):
            return [i for i in self]
    
    >>> n = NonRepeatingRandom(20)
    >>> n.get_all()
    [12, 14, 13, 2, 20, 4, 15, 16, 19, 1, 8, 6, 7, 9, 5, 11, 10, 3, 18, 17]
    

提交回复
热议问题