Shuffling a list of objects

PythonListRandomShuffle

Python Problem Overview


I have a list of objects and I want to shuffle them. I thought I could use the random.shuffle method, but this seems to fail when the list is of objects. Is there a method for shuffling objects or another way around this?

import random

class A:
    foo = "bar"

a1 = a()
a2 = a()
b = [a1, a2]

print(random.shuffle(b))

This will fail.

Python Solutions


Solution 1 - Python

random.shuffle should work. Here's an example, where the objects are lists:

from random import shuffle
x = [[i] for i in range(10)]
shuffle(x)

# print(x)  gives  [[9], [2], [7], [0], [4], [5], [3], [1], [8], [6]]
# of course your results will vary

Note that shuffle works in place, and returns None.

Solution 2 - Python

As you learned the in-place shuffling was the problem. I also have problem frequently, and often seem to forget how to copy a list, too. Using sample(a, len(a)) is the solution, using len(a) as the sample size. See https://docs.python.org/3.6/library/random.html#random.sample for the Python documentation.

Here's a simple version using random.sample() that returns the shuffled result as a new list.

import random

a = range(5)
b = random.sample(a, len(a))
print a, b, "two list same:", a == b
# print: [0, 1, 2, 3, 4] [2, 1, 3, 4, 0] two list same: False

# The function sample allows no duplicates.
# Result can be smaller but not larger than the input.
a = range(555)
b = random.sample(a, len(a))
print "no duplicates:", a == list(set(b))

try:
    random.sample(a, len(a) + 1)
except ValueError as e:
    print "Nope!", e

# print: no duplicates: True
# print: Nope! sample larger than population

Solution 3 - Python

It took me some time to get that too. But the documentation for shuffle is very clear:

> shuffle list x in place; return None.

So you shouldn't print(random.shuffle(b)). Instead do random.shuffle(b) and then print(b).

Solution 4 - Python

#!/usr/bin/python3

import random

s=list(range(5))
random.shuffle(s) # << shuffle before print or assignment
print(s)

# print: [2, 4, 1, 3, 0]

Solution 5 - Python

If you happen to be using numpy already (very popular for scientific and financial applications) you can save yourself an import.

import numpy as np    
np.random.shuffle(b)
print(b)

https://numpy.org/doc/stable/reference/random/generated/numpy.random.shuffle.html

Solution 6 - Python

>>> import random
>>> a = ['hi','world','cat','dog']
>>> random.shuffle(a,random.random)
>>> a
['hi', 'cat', 'dog', 'world']

It works fine for me. Make sure to set the random method.

Solution 7 - Python

If you have multiple lists, you might want to define the permutation (the way you shuffle the list / rearrange the items in the list) first and then apply it to all lists:

import random

perm = list(range(len(list_one)))
random.shuffle(perm)
list_one = [list_one[index] for index in perm]
list_two = [list_two[index] for index in perm]

Numpy / Scipy

If your lists are numpy arrays, it is simpler:

import numpy as np

perm = np.random.permutation(len(list_one))
list_one = list_one[perm]
list_two = list_two[perm]

mpu

I've created the small utility package mpu which has the consistent_shuffle function:

import mpu

# Necessary if you want consistent results
import random
random.seed(8)

# Define example lists
list_one = [1,2,3]
list_two = ['a', 'b', 'c']

# Call the function
list_one, list_two = mpu.consistent_shuffle(list_one, list_two)

Note that mpu.consistent_shuffle takes an arbitrary number of arguments. So you can also shuffle three or more lists with it.

Solution 8 - Python

For one-liners, userandom.sample(list_to_be_shuffled, length_of_the_list) with an example:

import random
random.sample(list(range(10)), 10)

outputs: [2, 9, 7, 8, 3, 0, 4, 1, 6, 5]

Solution 9 - Python

from random import random
my_list = range(10)
shuffled_list = sorted(my_list, key=lambda x: random())

This alternative may be useful for some applications where you want to swap the ordering function.

Solution 10 - Python

In some cases when using numpy arrays, using random.shuffle created duplicate data in the array.

An alternative is to use numpy.random.shuffle. If you're working with numpy already, this is the preferred method over the generic random.shuffle.

numpy.random.shuffle

Example

>>> import numpy as np
>>> import random

Using random.shuffle:

>>> foo = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> foo

array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])


>>> random.shuffle(foo)
>>> foo

array([[1, 2, 3],
       [1, 2, 3],
       [4, 5, 6]])

Using numpy.random.shuffle:

>>> foo = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> foo

array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])


>>> np.random.shuffle(foo)
>>> foo

array([[1, 2, 3],
       [7, 8, 9],
       [4, 5, 6]])

Solution 11 - Python

'print func(foo)' will print the return value of 'func' when called with 'foo'. 'shuffle' however has None as its return type, as the list will be modified in place, hence it prints nothing. Workaround:

# shuffle the list in place 
random.shuffle(b)

# print it
print(b)

If you're more into functional programming style you might want to make the following wrapper function:

def myshuffle(ls):
    random.shuffle(ls)
    return ls

Solution 12 - Python

One can define a function called shuffled (in the same sense of sort vs sorted)

def shuffled(x):
    import random
    y = x[:]
    random.shuffle(y)
    return y

x = shuffled([1, 2, 3, 4])
print x

Solution 13 - Python

import random
 
class a:
    foo = "bar"

a1 = a()
a2 = a()
a3 = a()
a4 = a()
b = [a1,a2,a3,a4]

random.shuffle(b)
print(b)

shuffle is in place, so do not print result, which is None, but the list.

Solution 14 - Python

you can either use shuffle or sample . both of which come from random module.

import random
def shuffle(arr1):
    n=len(arr1)
    b=random.sample(arr1,n)
    return b

OR

import random
def shuffle(arr1):
    random.shuffle(arr1)
    return arr1

Solution 15 - Python

Make sure you are not naming your source file random.py, and that there is not a file in your working directory called random.pyc.. either could cause your program to try and import your local random.py file instead of pythons random module.

Solution 16 - Python

You can go for this:

>>> A = ['r','a','n','d','o','m']
>>> B = [1,2,3,4,5,6]
>>> import random
>>> random.sample(A+B, len(A+B))
[3, 'r', 4, 'n', 6, 5, 'm', 2, 1, 'a', 'o', 'd']

if you want to go back to two lists, you then split this long list into two.

Solution 17 - Python

def shuffle(_list):
    if not _list == []:
        import random
        list2 = []
        while _list != []:
            card = random.choice(_list)
            _list.remove(card)
            list2.append(card)
        while list2 != []:
            card1 = list2[0]
            list2.remove(card1)
            _list.append(card1)
        return _list

Solution 18 - Python

you could build a function that takes a list as a parameter and returns a shuffled version of the list:

from random import *

def listshuffler(inputlist):
    for i in range(len(inputlist)):
        swap = randint(0,len(inputlist)-1)
        temp = inputlist[swap]
        inputlist[swap] = inputlist[i]
        inputlist[i] = temp
    return inputlist

Solution 19 - Python

""" to shuffle random, set random= True """

def shuffle(x,random=False):
     shuffled = []
     ma = x
     if random == True:
         rando = [ma[i] for i in np.random.randint(0,len(ma),len(ma))]
         return rando
     if random == False:
          for i in range(len(ma)):
          ave = len(ma)//3
          if i < ave:
             shuffled.append(ma[i+ave])
          else:
             shuffled.append(ma[i-ave])    
     return shuffled

Solution 20 - Python

import random
class a:
    foo = "bar"

a1 = a()
a2 = a()
b = [a1.foo,a2.foo]
random.shuffle(b)

Solution 21 - Python

In case you need an in-place shuffling and ability to manipulate seed, this snippet would help:

from random import randint

a = ['hi','world','cat','dog']
print(sorted(a, key=lambda _: randint(0, 1)))

Remember that "shuffling" is a sorting by randomised key.

Solution 22 - Python

The shuffling process is "with replacement", so the occurrence of each item may change! At least when when items in your list is also list.

E.g.,

ml = [[0], [1]] * 10

After,

random.shuffle(ml)

The number of [0] may be 9 or 8, but not exactly 10.

Solution 23 - Python

Plan: Write out the shuffle without relying on a library to do the heavy lifting. Example: Go through the list from the beginning starting with element 0; find a new random position for it, say 6, put 0’s value in 6 and 6’s value in 0. Move on to element 1 and repeat this process, and so on through the rest of the list

import random
iteration = random.randint(2, 100)
temp_var = 0
while iteration > 0:
    
    for i in range(1, len(my_list)): # have to use range with len()
        for j in range(1, len(my_list) - i):
            # Using temp_var as my place holder so I don't lose values
            temp_var = my_list[i]
            my_list[i] = my_list[j]
            my_list[j] = temp_var
            
        iteration -= 1

Solution 24 - Python

It works fine. I am trying it here with functions as list objects:

    from random import shuffle
    
    def foo1():
        print "foo1",
    
    def foo2():
        print "foo2",
    
    def foo3():
        print "foo3",
    
    A=[foo1,foo2,foo3]
    
    for x in A:
        x()
    
    print "\r"
    
    shuffle(A)
    for y in A:
        y()

It prints out: foo1 foo2 foo3 foo2 foo3 foo1 (the foos in the last row have a random order)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionutdiscantView Question on Stackoverflow
Solution 1 - Pythontom10View Answer on Stackoverflow
Solution 2 - PythonTedView Answer on Stackoverflow
Solution 3 - PythonOhad CohenView Answer on Stackoverflow
Solution 4 - PythonMichaelView Answer on Stackoverflow
Solution 5 - PythonfantabolousView Answer on Stackoverflow
Solution 6 - PythonDan LorencView Answer on Stackoverflow
Solution 7 - PythonMartin ThomaView Answer on Stackoverflow
Solution 8 - PythonweiyixieView Answer on Stackoverflow
Solution 9 - PythonJeffView Answer on Stackoverflow
Solution 10 - PythonGordon BeanView Answer on Stackoverflow
Solution 11 - PythonJonDoeView Answer on Stackoverflow
Solution 12 - PythonmalbarboView Answer on Stackoverflow
Solution 13 - Pythonravi tanwarView Answer on Stackoverflow
Solution 14 - Pythonravi tanwarView Answer on Stackoverflow
Solution 15 - Pythonuser3298224View Answer on Stackoverflow
Solution 16 - PythonkiriloffView Answer on Stackoverflow
Solution 17 - PythonPogramistView Answer on Stackoverflow
Solution 18 - Pythonuser8327014View Answer on Stackoverflow
Solution 19 - PythonJosh AnishView Answer on Stackoverflow
Solution 20 - PythonXavierView Answer on Stackoverflow
Solution 21 - PythonVladimir IgnatyevView Answer on Stackoverflow
Solution 22 - PythonGatsbyView Answer on Stackoverflow
Solution 23 - PythonEnberView Answer on Stackoverflow
Solution 24 - PythonStefan GruenwaldView Answer on Stackoverflow