Предположим, у меня есть следующий список:
foo = ['a', 'b', 'c', 'd', 'e']
Каков самый простой способ получить элемент случайным образом из этого списка?
Предположим, у меня есть следующий список:
foo = ['a', 'b', 'c', 'd', 'e']
Каков самый простой способ получить элемент случайным образом из этого списка?
Используйте 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))
Возможно, это уже ответ, но вы можете использовать random.shuffle
. Пример:
import random
foo = ['a', 'b', 'c', 'd', 'e']
random.shuffle(foo)
Вы можете просто:
from random import randint
foo = ["a", "b", "c", "d", "e"]
print(foo[randint(0,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
Следующий код демонстрирует, нужно ли вам производить те же элементы. Вы также можете указать, сколько образцов вы хотите извлечь.
Метод 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']
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
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)
Обратите внимание, что random.choices
подлежит замене, а random.sample
- без замены.
Также обратите внимание, что random.choices доступен начиная с версии 3.6 и новее, но не ранее!
Как случайным образом выбрать элемент из списка?
Предположим, у меня есть следующий список:
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
Это просто педантично, но секреты на самом деле не случайны, это криптографически безопасный псевдослучайный случай.
Начиная с 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.
Если вы хотите случайным образом выбрать более одного элемента из списка или выбрать элемент из набора, я бы рекомендовал использовать вместо него 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)
Кстати, модуль secrets
был добавлен в стандартную библиотеку Python в версии 3.6 python.org/dev/peps/pep-0506
Это код с переменной, определяющей случайный индекс:
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)
Мы также можем сделать это с помощью 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)
Зачем вам это делать, когда есть random.choice()
и random.randrange()
?
«random.choice ()» выдаст вам «IndexError: индекс списка вне допустимого диапазона» в пустом списке.
Как должно: вот для чего нужны исключения. Выбор из пустого списка является ошибкой. Возвращение None
просто отбрасывает банку до некоторой случайной более поздней точки, где недопустимый «элемент» вызывает исключение; или, что еще хуже, вы получаете неправильную программу вместо исключения, и вы даже не знаете об этом.
Можете ли вы добавить ссылку на randint , желательно в официальную документацию?
Предлагаю сценарий для удаления случайно выбранных элементов из списка, пока он не станет пустым:
Сохраните 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([])
Или вы можете просто random.shuffle
list
один раз и либо повторить его, либо выдвинуть для получения результатов. Либо приведет к совершенно адекватному потоку «выбор случайным образом без повторов», просто случайность будет введена в начале.
Теоретически вы можете использовать метод pop () набора, чтобы удалить произвольный элемент из набора и вернуть его, но, вероятно, он недостаточно случайный.
Если вам нужен индекс, просто используйте:
import random
foo = ['a', 'b', 'c', 'd', 'e']
print int(random.random() * len(foo))
print foo[int(random.random() * len(foo))]
random.choice делает то же самое :)
@tc. Фактически, он делает то же самое. Реализация random.choice(self, seq)
- return seq[int(self.random() * len(seq))]
.
@wim Это немного разочаровывает, но очень разочаровывает то, что это также определение randrange()
, что означает, например, random.SystemRandom().randrange(3<<51)
демонстрирует значительную предвзятость. Вздох ...
@ 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 () избегает такой предвзятости.)
@tc. Я полагаю, что что-то меньшее, чем 2**40
(что составляет 1099511627776), было бы достаточно малым, чтобы смещение не имело значения на практике? Это действительно должно быть указано в документации, потому что, если кто-то не дотошен, он может не ожидать, что проблемы возникнут из этой части своего кода.
@tc .: На самом деле random
использует getrandbits
, чтобы получить достаточное количество битов для генерации результата для больших randrange
s (random.choice
также использует это). Это верно как для 2.7, так и для 3.5. Он использует только self.random() * len(seq)
, когда getrandbits
недоступен. Он не делает глупостей, о которых вы думаете.
Если вам также нужен индекс, используйте random.randrange
from random import randrange
random_index = randrange(len(foo))
print(foo[random_index])
Вернут ли два последовательных вызова
random.choice(foo)
два разных результата?@EduardoPignatelli Каждый выбор случайен, поэтому он может возвращать два разных результата, но в зависимости от начального числа это не гарантируется. Если вы хотите выбрать n отдельных случайных элементов из списка lst , используйте
random.sample(lst, n)
по соответствующему примечанию,
Standard pseudo-random generators are not suitable for security/cryptographic purposes.
ссылка