How do I retrieve an item at random from the following list?
foo = ['a', 'b', 'c', 'd', 'e']
Best Answer
Use random.choice()
:
import randomfoo = ['a', 'b', 'c', 'd', 'e']print(random.choice(foo))
For cryptographically secure random choices (e.g., for generating a passphrase from a wordlist), use secrets.choice()
:
import secretsfoo = ['battery', 'correct', 'horse', 'staple']print(secrets.choice(foo))
secrets
is new in Python 3.6. On older versions of Python you can use the random.SystemRandom
class:
import randomsecure_random = random.SystemRandom()print(secure_random.choice(foo))
If you want to randomly select more than one item from a list, or select an item from a set, I'd recommend using random.sample
instead.
import randomgroup_of_items = {'a', 'b', 'c', 'd', 'e'} # a sequence or set will work here.num_to_select = 2 # set the number to select here.list_of_random_items = random.sample(group_of_items, num_to_select)first_random_item = list_of_random_items[0]second_random_item = list_of_random_items[1]
If you're only pulling a single item from a list though, choice is less clunky, as using sample would have the syntax random.sample(some_list, 1)[0]
instead of random.choice(some_list)
.
Unfortunately though, choice only works for a single output from sequences (such as lists or tuples). Though random.choice(tuple(some_set))
may be an option for getting a single item from a set.
EDIT: Using Secrets
As many have pointed out, if you require more secure pseudorandom samples, you should use the secrets module:
import secrets # imports secure module.secure_random = secrets.SystemRandom() # creates a secure random object.group_of_items = {'a', 'b', 'c', 'd', 'e'} # a sequence or set will work here.num_to_select = 2 # set the number to select here.list_of_random_items = secure_random.sample(group_of_items, num_to_select)first_random_item = list_of_random_items[0]second_random_item = list_of_random_items[1]
EDIT: Pythonic One-Liner
If you want a more pythonic one-liner for selecting multiple items, you can use unpacking.
import randomfirst_random_item, second_random_item = random.sample({'a', 'b', 'c', 'd', 'e'}, 2)
If you also need the index, use random.randrange
from random import randrangerandom_index = randrange(len(foo))print(foo[random_index])
As of Python 3.6 you can use the secrets
module, which is preferable to the random
module for cryptography or security uses.
To print a random element from a list:
import secretsfoo = ['a', 'b', 'c', 'd', 'e']print(secrets.choice(foo))
To print a random index:
print(secrets.randbelow(len(foo)))
For details, see PEP 506.
I propose a script for removing randomly picked up items off a list until it is empty:
Maintain a set
and remove randomly picked up element (with choice
) until list is empty.
s=set(range(1,6))import randomwhile len(s)>0:s.remove(random.choice(list(s)))print(s)
Three runs give three different answers:
>>> set([1, 3, 4, 5])set([3, 4, 5])set([3, 4])set([4])set([])>>> set([1, 2, 3, 5])set([2, 3, 5])set([2, 3])set([2])set([])>>> set([1, 2, 3, 5])set([1, 2, 3])set([1, 2])set([1])set([])
foo = ['a', 'b', 'c', 'd', 'e']number_of_samples = 1
In Python 2:
random_items = random.sample(population=foo, k=number_of_samples)
In Python 3:
random_items = random.choices(population=foo, k=number_of_samples)
NumPy solution: numpy.random.choice
For this question, it works the same as the accepted answer (import random; random.choice()
), but I added it because the programmer may have imported NumPy already (like me)
And also there are some differences between the two methods that may concern your actual use case.
import numpy as npnp.random.choice(foo) # randomly selects a single item
For reproducibility, you can do:
np.random.seed(123)np.random.choice(foo) # first call will always return 'c'
For samples of one or more items, returned as an array
, pass the size
argument:
np.random.choice(foo, 5) # sample with replacement (default)np.random.choice(foo, 5, False) # sample without replacement
I usually use the random module for working with lists and randomization:
import randomfoo = ['a', 'b', 'c', 'd', 'e']print(random.choice(foo))
If you need the index, just use:
import randomfoo = ['a', 'b', 'c', 'd', 'e']print int(random.random() * len(foo))print foo[int(random.random() * len(foo))]
random.choice does the same:)
How to randomly select an item from a list?
Assume I have the following list:
foo = ['a', 'b', 'c', 'd', 'e']
What is the simplest way to retrieve an item at random from this list?
If you want close to truly random, then I suggest secrets.choice
from the standard library (New in Python 3.6.):
>>> from secrets import choice # Python 3 only>>> choice(list('abcde'))'c'
The above is equivalent to my former recommendation, using a SystemRandom
object from the random
module with the choice
method - available earlier in Python 2:
>>> import random # Python 2 compatible>>> sr = random.SystemRandom()>>> foo = list('abcde')>>> foo['a', 'b', 'c', 'd', 'e']
And now:
>>> sr.choice(foo)'d'>>> sr.choice(foo)'e'>>> sr.choice(foo)'a'>>> sr.choice(foo)'b'>>> sr.choice(foo)'a'>>> sr.choice(foo)'c'>>> sr.choice(foo)'c'
If you want a deterministic pseudorandom selection, use the choice
function (which is actually a bound method on a Random
object):
>>> random.choice<bound method Random.choice of <random.Random object at 0x800c1034>>
It seems random, but it's actually not, which we can see if we reseed it repeatedly:
>>> random.seed(42); random.choice(foo), random.choice(foo), random.choice(foo)('d', 'a', 'b')>>> random.seed(42); random.choice(foo), random.choice(foo), random.choice(foo)('d', 'a', 'b')>>> random.seed(42); random.choice(foo), random.choice(foo), random.choice(foo)('d', 'a', 'b')>>> random.seed(42); random.choice(foo), random.choice(foo), random.choice(foo)('d', 'a', 'b')>>> random.seed(42); random.choice(foo), random.choice(foo), random.choice(foo)('d', 'a', 'b')
A comment:
This is not about whether random.choice is truly random or not. If you fix the seed, you will get the reproducible results -- and that's what seed is designed for. You can pass a seed to SystemRandom, too.
sr = random.SystemRandom(42)
Well, yes you can pass it a "seed" argument, but you'll see that the SystemRandom
object simply ignores it:
def seed(self, *args, **kwds):"Stub method. Not used for a system random number generator."return None
In short, use random.sample
method
The sample
method returns a new list containing elements from the population while leaving the original population unchanged. The resulting list is in selection order so that all sub-slices will also be valid random samples.
import randomlst = ['a', 'b', 'c', 'd', 'e']random.seed(0) # remove this line, if you want different results for each runrand_lst = random.sample(lst,3) # 3 is the number of sample you want to retrieveprint(rand_lst)Output:['d', 'e', 'a']
here is a running codehttps://onecompiler.com/python/3xem5jjvz
This is the code with a variable that defines the random index:
import randomfoo = ['a', 'b', 'c', 'd', 'e']randomindex = random.randint(0,len(foo)-1) print (foo[randomindex])## print (randomindex)
This is the code without the variable:
import randomfoo = ['a', 'b', 'c', 'd', 'e']print (foo[random.randint(0,len(foo)-1)])
And this is the code in the shortest and smartest way to do it:
import randomfoo = ['a', 'b', 'c', 'd', 'e']print(random.choice(foo))
(python 2.7)
Random item selection:
import randommy_list = [1, 2, 3, 4, 5]num_selections = 2new_list = random.sample(my_list, num_selections)
To preserve the order of the list, you could do:
randIndex = random.sample(range(len(my_list)), n_selections)randIndex.sort()new_list = [my_list[i] for i in randIndex]
Duplicate of https://stackoverflow.com/a/49682832/4383027
You could just:
from random import randintfoo = ["a", "b", "c", "d", "e"]print(foo[randint(0,4)])
This may already be an answer, but you can use random.shuffle
. Example:
import randomfoo = ['a', 'b', 'c', 'd', 'e']random.shuffle(foo)
The recommended numpy
way is now to use an explicit RNG:
from numpy.random import default_rngrng = default_rng()rng.choice(foo)
To select multiple values from a list foo = ['a', 'b', 'c', 'd', 'e']
, see the following table for the relevant method in each module.
random
random.choices(foo, k=4)
random.sample(foo, k=4)
numpy
rng = np.random.default_rng()
rng.choice(foo, size=4)
rng = np.random.default_rng()
rng.choice(foo, size=4, replace=False)
pandas
s = pd.Series(foo)
s.sample(n=4, replace=True)
s = pd.Series(foo)
s.sample(n=4)
In terms of performance, it depends on the size of the original data and the size of the sampled data but in general, it's better to use random
if the data type is a Python data structure such as a list, whereas numpy
/pandas
perform best on their native objects, e.g. numpy ndarray, pandas Series.
For example, in the following benchmark (tested on Python 3.11.4, numpy 1.25.2 and pandas 2.0.3) where 20k items are sampled from an object of length 100k, numpy and pandas are very fast on an array and a Series but slow on a list, while random.choices
is the fastest on a list.
import timeitsetup = """import randomimport pandas as pdimport numpy as npli = list(range(100000))ar = np.array(li)sr = pd.Series(li)n = len(li)//5"""min(timeit.repeat("random.choices(li, k=n)", setup, number=100)) # 0.5333051000052365 min(timeit.repeat("np.random.default_rng().choice(li, size=n)", setup, number=100)) # 0.9663617000041995 min(timeit.repeat("pd.Series(li).sample(n=n, replace=True)", setup, number=100)) # 3.30128049999621 min(timeit.repeat("random.choices(ar, k=n)", setup, number=100)) # 0.5489860999950906 min(timeit.repeat("np.random.default_rng().choice(ar, size=n)", setup, number=100)) # 0.030448100005742162 min(timeit.repeat("pd.Series(ar).sample(n=n, replace=True)", setup, number=100)) # 0.07655550000345102 min(timeit.repeat("random.choices(sr, k=n)", setup, number=100)) # 6.577740900000208 min(timeit.repeat("np.random.default_rng().choice(sr, size=n)", setup, number=100)) # 0.0323493999967468 min(timeit.repeat("sr.sample(n=n, replace=True)", setup, number=100)) # 0.06925690000207396
We can also do this using randint.
from random import randintl= ['a','b','c']def get_rand_element(l):if l:return l[randint(0,len(l)-1)]else:return Noneget_rand_element(l)