如何从列表中随机选择一个项目?

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?

转载于:https://stackoverflow.com/questions/306400/how-to-randomly-select-an-item-from-a-list

14个回答

If you also need the index, use random.randrange

from random import randrange
random_index = randrange(len(foo))
print(foo[random_index])
csdnceshi78
程序go That's O(n) whereas Juampi's perfectly fine method is O(1).
接近 7 年之前 回复
csdnceshi55
~Onlooker I would prefer random.choice(list(enumerate(foo))) for this..
7 年多之前 回复

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 random
group_of_items = {1, 2, 3, 4}               # 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 = {1, 2, 3, 4}               # 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]

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 using a SystemRandom object from the random module with the choice method:

>>> import random
>>> 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')

We can also do this using randint.

from random import randint
l= ['a','b','c']

def get_rand_element(l):
    if l:
        return l[randint(0,len(l)-1)]
    else:
        return None

get_rand_element(l)
csdnceshi55
~Onlooker As it should: that's what exceptions are for. Choosing from an empty list is an error. Returning None just kicks the can to some random later point where the invalid "element" triggers an exception; or worse yet, you get an incorrect program instead of an exception, and you don't even know it.
大约 3 年之前 回复
csdnceshi57
perhaps? "random.choice()" will give you "IndexError: list index out of range" on empty list.
大约 3 年之前 回复
csdnceshi55
~Onlooker Why on earth would you do it this way, when there's random.choice() and random.randrange()?
4 年多之前 回复
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)
weixin_41568196
撒拉嘿哟木头 Also note that random.choices is available from 3.6 and later, not before!
接近 2 年之前 回复
csdnceshi61
derek5. Note that random.choices is with replacement while random.sample is without replacement.
2 年多之前 回复

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 random

while 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([])
csdnceshi77
狐狸.fox Theoretically you can use the pop() method of a set to remove an arbitrary element from a set and return it, but it's probably not random enough.
4 年多之前 回复
csdnceshi59
ℙℕℤℝ Or you could just random.shuffle the list once and either iterate it or pop it to produce results. Either would result in a perfectly adequate "select randomly with no repeats" stream, it's just that the randomness would be introduced at the beginning.
接近 5 年之前 回复

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 secrets
foo = ['a', 'b', 'c', 'd', 'e']
print(secrets.choice(foo))

To print a random index:

print(secrets.randbelow(len(foo)))

For details, see PEP 506.

if you need the index just use:

import random
foo = ['a', 'b', 'c', 'd', 'e']
print int(random.random() * len(foo))
print foo[int(random.random() * len(foo))]

random.choice does the same:)

csdnceshi65
larry*wei Actually, random uses getrandbits to get an adequate number of bits to generate a result for larger randranges (random.choice is also using that). This is true on both 2.7 and 3.5. It only uses self.random() * len(seq) when getrandbits is not available. It's not doing the stupid thing you think it is.
接近 5 年之前 回复
csdnceshi62
csdnceshi62 I suppose anything less than about 2**40, (which is 1099511627776), would be small enough for the bias to not matter in practice? This should really be pointed out in the documentation, because if somebody is not meticulous, they might not expect problems to come from this part of their code.
5 年多之前 回复
csdnceshi57
perhaps? Ultimately it's because a float (an IEEE double) can only take a finite number of values in [0,1). Random.random() generates its output in the traditional way: pick a random integer in [0, 2**53) and divide by 2**53 (53 is the number of bits in a double). So random() returns 2**53 equiprobable doubles, and you can divide this evenly into N outputs only if N is a power of 2. The bias is small for small N, but see collections.Counter(random.SystemRandom().randrange(3<<51)%6 for i in range(100000)).most_common(). (Java's Random.nextInt() avoids such bias.)
6 年多之前 回复
csdnceshi57
perhaps? That's a little disappointing, but the very disappointing thing is that's also the definition of randrange() which means e.g. random.SystemRandom().randrange(3<<51) exhibits significant bias. Sigh...
7 年多之前 回复
csdnceshi70
笑故挽风 Actually, it does do essentially the same. Implementation of random.choice(self, seq) is return seq[int(self.random() * len(seq))].
7 年多之前 回复

This is the code with a variable that defines the random index:

import random

foo = ['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 random

foo = ['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 random

foo = ['a', 'b', 'c', 'd', 'e']
print(random.choice(foo))

(python 2.7)

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) & also there are some differences between the two methods that may concern your actual use case.

import numpy as np    
np.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
共14条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐