How do I shuffle a list of objects? I tried random.shuffle
:
import random
b = [object(), object()]
print(random.shuffle(b))
But it outputs:
None
How do I shuffle a list of objects? I tried random.shuffle
:
import random
b = [object(), object()]
print(random.shuffle(b))
But it outputs:
None
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)
# print(x) gives [[9], [2], [7], [0], [4], [5], [3], [1], [8], [6]]
Note that shuffle
works in place, and returns None
.
More generally in Python, mutable objects can be passed into functions, and when a function mutates those objects, the standard is to return None
(rather than, say, the mutated object).
random
module's documentation.
random.sample(x, len(x))
or just make a copy and shuffle
that. For list.sort
which has a similar issue, there's now list.sorted
, but there's not a similar variant for shuffle
.
from random import SystemRandom
instead; add cryptorand = SystemRandom()
and change row 3 to cryptorand.shuffle(x)
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
old = [1,2,3,4,5]; new = list(old); random.shuffle(new); print(old); print(new)
(replace ; with newlines)
sample()
is particularly helpful for prototyping a data analysis. sample(data, 2)
for setting up the glue code of a pipeline, then "widening" it step-wise, up to len(data)
.
Aug 30, 2019 at 13:32
The documentation for random.shuffle
states that it will
Shuffle the sequence x in place.
Don't do:
print(random.shuffle(xs)) # WRONG!
Instead, do:
random.shuffle(xs)
print(xs)
print(random.shuffle(my_list) or my_list)
Mar 29, 2023 at 10:33
#!/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]
For numpy
(popular library for scientific and financial applications), use np.random.shuffle
:
import numpy as np
b = np.arange(10)
np.random.shuffle(b)
print(b)
random
module, there is the seed()
function, which can be used for creating reproducible outputs (docs.python.org/3/library/random.html#random.seed)
>>> 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.
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]
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]
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.
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]
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.
sorted
, this is a functional shuffle (if you're into that sort of thing).
Nov 15, 2017 at 19:52
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
.
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]])
numpy.random.permutation
may be of interest: stackoverflow.com/questions/15474159/shuffle-vs-permute-numpy
Dec 19, 2016 at 19:57
random.shuffle
documentation should shout Do not use with numpy arrays
Oct 13, 2019 at 7:50
'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
random.sample(ls, len(ls))
if you really want to go down that route.
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
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.
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
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.
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.
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.
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
_list.extend(list2)
, which is more succinct AND more efficient.
Oct 13, 2018 at 8:36
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
""" 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
import random
class a:
foo = "bar"
a1 = a()
a2 = a()
b = [a1.foo,a2.foo]
random.shuffle(b)
For anyone interested in using the Index Sequential Method (Ouarda et.al., 1997) to reorder a list:
def ISM(dList):
nList = dList.copy()
dRng = range(len(dList))
for i in dRng[:-1]:
nList[i] = dList[i+1]
nList[-1] = dList[0]
return nList
This will work for a single value list...
valList = [1,2,3,4,5,6,7]
for l in range(len(valList)):
print(valList)
dataList = ISM(valList)
This will print out...
[1, 2, 3, 4, 5, 6, 7]
[2, 3, 4, 5, 6, 7, 1]
[3, 4, 5, 6, 7, 1, 2]
[4, 5, 6, 7, 1, 2, 3]
[5, 6, 7, 1, 2, 3, 4]
[6, 7, 1, 2, 3, 4, 5]
[7, 1, 2, 3, 4, 5, 6]
or a list of nested lists...
nestedList = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
for l in range(len(nestedList)):
print(nestedList)
nestedList = ISM(nestedList)
This will print out...
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
[[4, 5, 6], [7, 8, 9], [10, 11, 12], [1, 2, 3]]
[[7, 8, 9], [10, 11, 12], [1, 2, 3], [4, 5, 6]]
[[10, 11, 12], [1, 2, 3], [4, 5, 6], [7, 8, 9]]
@Shantanu Sharma provides some great methods for breaking a list of values into a sequence of nested lists of size n.
Here's the method I used...
valList = [1,2,3,4,5,6,7,8,9,10,11,12]
# Yield successive n-sized lists from l
def SequenceList(l, n):
# looping till length l
for i in range(0, len(l), n):
yield l[i:i + n]
nestedList = list(SequenceList(valList, 3))
This will print out...
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
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.
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
my_list[i], my_list[j] = my_list[j], my_list[i]
Jun 12, 2018 at 17:58
You can use random.choices()
to shuffle your list.
TEAMS = [A,B,C,D,E,F,G,H]
random.choices(TEAMS,k = len(TEAMS))
The above code will return a randomized list same length as your previous list.
Hope It Helps !!!
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)
shuffle()
options for that. Just userandom.sample(b, len(b))
instead.shuffle
? It should beNone
as it is shuffling the array in place