Как я могу случайным образом выбрать элемент из списка?

avatar
Ray
20 ноября 2008 в 18:42
1722150
15
2023

Предположим, у меня есть следующий список:

foo = ['a', 'b', 'c', 'd', 'e']

Каков самый простой способ получить элемент случайным образом из этого списка?

Источник

Ответы (15)

avatar
Pēteris Caune
20 ноября 2008 в 18:46
3025

Используйте random.choice():

import random

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

Для криптографически безопасного случайного выбора (например, для генерации ключевой фразы из списка слов) используйте secrets.choice():

import secrets

foo = ['battery', 'correct', 'horse', 'staple']
print(secrets.choice(foo))

secrets является новым в Python 3.6. В более старых версиях Python вы можете использовать класс random.SystemRandom:

import random

secure_random = random.SystemRandom()
print(secure_random.choice(foo))
Eduardo Pignatelli
7 декабря 2018 в 17:13
4

Вернут ли два последовательных вызова random.choice(foo) два разных результата?

Graham
23 декабря 2018 в 17:02
60

@EduardoPignatelli Каждый выбор случайен, поэтому он может возвращать два разных результата, но в зависимости от начального числа это не гарантируется. Если вы хотите выбрать n отдельных случайных элементов из списка lst , используйте random.sample(lst, n)

XoXo
30 января 2019 в 19:46
8

по соответствующему примечанию, Standard pseudo-random generators are not suitable for security/cryptographic purposes. ссылка

avatar
Jax
6 ноября 2020 в 03:39
2

Возможно, это уже ответ, но вы можете использовать random.shuffle. Пример:

import random
foo = ['a', 'b', 'c', 'd', 'e']
random.shuffle(foo)
avatar
Evan Schwartzentruber
28 мая 2020 в 06:06
3

Вы можете просто:

from random import randint

foo = ["a", "b", "c", "d", "e"]

print(foo[randint(0,4)])
avatar
Solomon Vimal
27 августа 2019 в 21:29
4

Случайный выбор элемента:

import random

my_list = [1, 2, 3, 4, 5]
num_selections = 2

new_list = random.sample(my_list, num_selections)

Чтобы сохранить порядок в списке, вы можете сделать:

randIndex = random.sample(range(len(my_list)), n_selections)
randIndex.sort()
new_list = [my_list[i] for i in randIndex]

Дубликат https://coderhelper.com/a/49682832/4383027

avatar
Memin
12 октября 2018 в 15:47
3

Следующий код демонстрирует, нужно ли вам производить те же элементы. Вы также можете указать, сколько образцов вы хотите извлечь.
Метод sample возвращает новый список, содержащий элементы из совокупности, оставляя исходную совокупность неизменной. Результирующий список находится в порядке выбора, так что все субсрезы также будут действительными случайными выборками.

import random as random
random.seed(0)  # don't use seed function, if you want different results in each run
print(random.sample(foo,3))  # 3 is the number of sample you want to retrieve

Output:['d', 'e', 'a']
avatar
C8H10N4O2
17 июля 2018 в 16:20
18

NumPy решение: numpy.random.choice

Для этого вопроса он работает так же, как принятый ответ (import random; random.choice()), но я добавил его, потому что программист, возможно, уже импортировал NumPy (как и я)

А также есть некоторые различия между двумя методами, которые могут касаться вашего фактического использования.

import numpy as np
np.random.choice(foo) # randomly selects a single item

Для воспроизводимости вы можете сделать:

np.random.seed(123)
np.random.choice(foo) # first call will always return 'c'

Для образцов одного или нескольких элементов , возвращенных как array, передайте аргумент size:

np.random.choice(foo, 5)          # sample with replacement (default)
np.random.choice(foo, 5, False)   # sample without replacement
avatar
Fardin Abdi
29 ноября 2017 в 16:40
23
foo = ['a', 'b', 'c', 'd', 'e']
number_of_samples = 1

В Python 2:

random_items = random.sample(population=foo, k=number_of_samples)

В Python 3:

random_items = random.choices(population=foo, k=number_of_samples)
CentAu
5 марта 2018 в 23:43
11

Обратите внимание, что random.choices подлежит замене, а random.sample - без замены.

Cyril N.
20 октября 2018 в 09:43
2

Также обратите внимание, что random.choices доступен начиная с версии 3.6 и новее, но не ранее!

avatar
Aaron Hall
23 июня 2017 в 22:22
12

Как случайным образом выбрать элемент из списка?

Предположим, у меня есть следующий список:

foo = ['a', 'b', 'c', 'd', 'e']  

Каков самый простой способ получить элемент случайным образом из этого списка?

Если вы хотите закрыть до действительно случайным , то я предлагаю secrets.choice из стандартной библиотеки (Новое в Python 3.6.):

>>> from secrets import choice         # Python 3 only
>>> choice(list('abcde'))
'c'

Вышеупомянутое эквивалентно моей предыдущей рекомендации с использованием объекта SystemRandom из модуля random с методом choice, доступным ранее в Python 2:

>>> import random                      # Python 2 compatible
>>> sr = random.SystemRandom()
>>> foo = list('abcde')
>>> foo
['a', 'b', 'c', 'd', 'e']

А теперь:

>>> 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'

Если вам нужен детерминированный псевдослучайный выбор, используйте функцию choice (которая на самом деле является связанным методом для объекта Random):

>>> random.choice
<bound method Random.choice of <random.Random object at 0x800c1034>>

Это кажется случайным, но на самом деле это не так, что мы сможем увидеть, если повторно заполнили его повторно:

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

Комментарий:

Дело не в том, действительно ли random.choice является случайным или нет. Если вы исправите семя, вы получите воспроизводимые результаты - и для этого семя предназначено. Вы также можете передать семя в SystemRandom. sr = random.SystemRandom(42)

Ну да, вы можете передать ему аргумент "начальный", но вы увидите, что объект SystemRandom просто игнорирует его:

def seed(self, *args, **kwds):
    "Stub method.  Not used for a system random number generator."
    return None
Paul
10 января 2021 в 22:07
0

Это просто педантично, но секреты на самом деле не случайны, это криптографически безопасный псевдослучайный случай.

avatar
Chris_Rands
5 декабря 2016 в 16:52
48

Начиная с Python 3.6, вы можете использовать модуль secrets, который предпочтительнее модуля random для использования в <181060> или безопасности.

Чтобы напечатать случайный элемент из списка:

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

Чтобы напечатать случайный индекс:

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

Подробнее см. PEP 506.

avatar
Paul
27 мая 2015 в 17:07
239

Если вы хотите случайным образом выбрать более одного элемента из списка или выбрать элемент из набора, я бы рекомендовал использовать вместо него random.sample.

import random
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 = random.sample(group_of_items, num_to_select)
first_random_item = list_of_random_items[0]
second_random_item = list_of_random_items[1] 

Если вы выбираете только один элемент из списка, выбор будет менее громоздким, так как использование sample будет иметь синтаксис random.sample(some_list, 1)[0] вместо random.choice(some_list).

К сожалению, выбор работает только для одного вывода из последовательностей (таких как списки или кортежи). Хотя random.choice(tuple(some_set)) может быть вариантом получения одного предмета из набора.

РЕДАКТИРОВАТЬ: Использование секретов

Как многие отмечали, если вам требуются более безопасные псевдослучайные образцы, вы должны использовать модуль секретов:

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]

РЕДАКТИРОВАТЬ: Pythonic One-Liner

Если вам нужен более питонический однострочник для выбора нескольких элементов, вы можете использовать распаковку.

import random
first_random_item, second_random_item = random.sample({'a', 'b', 'c', 'd', 'e'}, 2)
and1er
13 декабря 2019 в 06:53
4

Кстати, модуль secrets был добавлен в стандартную библиотеку Python в версии 3.6 python.org/dev/peps/pep-0506

avatar
Liam
25 мая 2015 в 14:57
8

Это код с переменной, определяющей случайный индекс:

import random

foo = ['a', 'b', 'c', 'd', 'e']
randomindex = random.randint(0,len(foo)-1) 
print (foo[randomindex])
## print (randomindex)

Это код без переменной:

import random

foo = ['a', 'b', 'c', 'd', 'e']
print (foo[random.randint(0,len(foo)-1)])

И это самый короткий и умный способ сделать это:

import random

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

(Python 2.7)

avatar
Abdul Majeed
5 августа 2014 в 07:28
-1

Мы также можем сделать это с помощью 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)
alexis
19 марта 2016 в 15:10
22

Зачем вам это делать, когда есть random.choice() и random.randrange()?

Abdul Majeed
5 сентября 2017 в 05:45
0

«random.choice ()» выдаст вам «IndexError: индекс списка вне допустимого диапазона» в пустом списке.

alexis
5 сентября 2017 в 09:27
9

Как должно: вот для чего нужны исключения. Выбор из пустого списка является ошибкой. Возвращение None просто отбрасывает банку до некоторой случайной более поздней точки, где недопустимый «элемент» вызывает исключение; или, что еще хуже, вы получаете неправильную программу вместо исключения, и вы даже не знаете об этом.

Peter Mortensen
31 июля 2021 в 19:00
0

Можете ли вы добавить ссылку на randint , желательно в официальную документацию?

avatar
kiriloff
13 мая 2013 в 02:47
36

Предлагаю сценарий для удаления случайно выбранных элементов из списка, пока он не станет пустым:

Сохраните set и удалите случайно выбранный элемент (с choice), пока список не станет пустым.

s=set(range(1,6))
import random

while len(s)>0:
  s.remove(random.choice(list(s)))
  print(s)

Три прогона дают три разных ответа:

>>> 
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([])
ShadowRanger
25 декабря 2015 в 03:23
23

Или вы можете просто random.shuffle list один раз и либо повторить его, либо выдвинуть для получения результатов. Либо приведет к совершенно адекватному потоку «выбор случайным образом без повторов», просто случайность будет введена в начале.

Joubarc
17 июня 2016 в 07:07
2

Теоретически вы можете использовать метод pop () набора, чтобы удалить произвольный элемент из набора и вернуть его, но, вероятно, он недостаточно случайный.

avatar
Janek Olszak
23 декабря 2012 в 22:06
12

Если вам нужен индекс, просто используйте:

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

random.choice делает то же самое :)

wim
12 апреля 2013 в 04:56
2

@tc. Фактически, он делает то же самое. Реализация random.choice(self, seq) - return seq[int(self.random() * len(seq))].

tc.
13 апреля 2013 в 23:55
2

@wim Это немного разочаровывает, но очень разочаровывает то, что это также определение randrange(), что означает, например, random.SystemRandom().randrange(3<<51) демонстрирует значительную предвзятость. Вздох ...

tc.
18 января 2014 в 16:37
7

@ kevinsa5 В конечном итоге это потому, что float (двойной IEEE) может принимать только конечное число значений в [0,1). Random.random() генерирует свой вывод традиционным способом: выберите случайное целое число в [0, 2**53) и разделите на 2**53 (53 - количество битов в двойном). Итак, random() возвращает 2 ** 53 равновероятных удвоения, и вы можете разделить это поровну на N выходов, только если N является степенью 2. Смещение мало для малых N, но см. collections.Counter(random.SystemRandom().randrange(3<<51)%6 for i in range(100000)).most_common(). (Java Random.nextInt () избегает такой предвзятости.)

Evgeni Sergeev
29 мая 2015 в 01:28
1

@tc. Я полагаю, что что-то меньшее, чем 2**40 (что составляет 1099511627776), было бы достаточно малым, чтобы смещение не имело значения на практике? Это действительно должно быть указано в документации, потому что, если кто-то не дотошен, он может не ожидать, что проблемы возникнут из этой части своего кода.

ShadowRanger
25 декабря 2015 в 03:32
1

@tc .: На самом деле random использует getrandbits, чтобы получить достаточное количество битов для генерации результата для больших randrange s (random.choice также использует это). Это верно как для 2.7, так и для 3.5. Он использует только self.random() * len(seq), когда getrandbits недоступен. Он не делает глупостей, о которых вы думаете.

avatar
Juampi
11 сентября 2012 в 15:31
170

Если вам также нужен индекс, используйте random.randrange

from random import randrange
random_index = randrange(len(foo))
print(foo[random_index])