On Sun, Aug 2, 2020 at 8:05 PM <raymond.hettinger@gmail.com> wrote:
FWIW, we've already documented a clean way to do it, https://docs.python.org/3/library/random.html#random.shuffle , "To shuffle an immutable sequence and return a new shuffled list, use sample(x, k=len(x)) instead."

one downside of this is that it won't work on a non-sized iterable -- but I suppose that's not really an important use-case. It Is a use case, though, 'cause while a shuffled collection is going to be sized by definition, the source could be a generator or some other non-sized iterable. But not hard to "realize" the iterable first by making it a list or tuple.

My other question was about performance. Without looking at the code, I thought it *might* be faster to shuffle than build up a list with multiple samples. but in profiling, the sample version is only about 30% slower. (for this one example :-) )

In [13]: def shuffled_1(it):
    ...:     result = list(it)
    ...:     random.shuffle(result)
    ...:     return result       

In [14]: def shuffled_2(it):
    ...:     return random.sample(it, k=len(it))
 
In [15]: %timeit shuffled_1(population)
3.71 ms ± 30.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [16]: %timeit shuffled_2(population)
4.23 ms ± 23.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

where:

In [17]: population   
Out[17]: range(0, 10000)

So yeah, this is a fine solution.

-CHB


--
Christopher Barker, PhD

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython