random.SystemRandom().randint() inefficient

Alan Bawden alan at csail.mit.edu
Wed Jul 27 15:42:25 EDT 2022


Cecil Westerhof <Cecil at decebal.nl> writes:

   Alan Bawden <alan at csail.mit.edu> writes:

   > Cecil Westerhof <Cecil at decebal.nl> writes:
   >
   >    Yes, I try to select a random element, but it has also to be removed,
   >    because an element should not be used more as once.
   >
   > Instead of using pop to do that why not something like:
   >
   >     def lazy_shuffle(seq):
   >         """
   >         Generate the elements of the given sequence in a random order.
   >         """
   >         # Delete the next line if you want to use a different version of
   >         # randrange:
   >         from random import randrange
   >         # Delete the next line if SEQ is already a mutable sequence and you
   >         # are willing to have it destroyed by this process:
   >         seq = list(seq)
   >         n = len(seq)
   >         while n:
   >             i = randrange(n)
   >             yield seq[i]
   >             n -= 1
   >             if i < n:
   >                 seq[i] = seq[n]

   That looks interesting.
   But there is on problem. (I think.)
   The list is only partly eaten and I will eat a lot of sequences. So a
   lot of sequences will be left in the runtime.
   Or is there a way to destroy the lazy_shuffle when it is not needed
   anymore?

You don't have to worry about that.  That's what Garbage Collection is
for.  After you drop the last reference to the generator, the GC will
destroy it for you.  Welcome to Python.

BTW, what I wrote might be slightly faster if you replace it with:

    while n:
        i = randrange(n)
        yield seq[i]
        n -= 1
        seq[i] = seq[n]

That will save you some time spent testing and branching.

-- 
Alan Bawden


More information about the Python-list mailing list