목록에서 항목을 무작위로 선택하는 방법은 무엇입니까?


1758

다음 목록이 있다고 가정하십시오.

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

이 목록에서 무작위로 항목을 검색하는 가장 간단한 방법은 무엇입니까?

답변:


2677

사용하다 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))

secretsPython 3.6의 새로운 기능으로, 이전 버전의 Python에서는 다음 random.SystemRandom클래스를 사용할 수 있습니다 .

import random

secure_random = random.SystemRandom()
print(secure_random.choice(foo))

3
두 번 연속 호출하면 random.choice(foo)서로 다른 결과 가 반환됩니까?
Eduardo Pignatelli

34
@EduardoPignatelli 각 선택은 무작위이므로 두 가지 다른 결과를 반환 할 있지만 시작 시드에 따라 보장되지는 않습니다. 리스트 lst 에서 n 개의 다른 랜덤 요소 를 선택 하려면random.sample(lst, n)
Graham

6
관련 메모, Standard pseudo-random generators are not suitable for security/cryptographic purposes. 심판
Xiao

184

목록에서 둘 이상의 항목을 임의로 선택하거나 세트에서 항목을 선택하려면 random.sample대신 사용 하는 것이 좋습니다 .

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] 

그래도 목록에서 단일 항목 만 가져 오는 경우 sample을 사용하는 random.sample(some_list, 1)[0]대신 구문이 사용되므로 선택이 덜 복잡합니다 random.choice(some_list).

불행히도, 선택은 시퀀스 (예 : 목록 또는 튜플)의 단일 출력에 대해서만 작동합니다. 비록 random.choice(tuple(some_set))세트에서 단일 항목을 취득하기위한 옵션이 될 수 있습니다.

편집 : 비밀 사용

많은 사람들이 지적했듯이 더 안전한 의사 난수 샘플이 필요한 경우 secrets 모듈을 사용해야합니다.

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]

편집 : Pythonic One-Liner

여러 항목을 선택하기 위해 더 많은 파이 토닉 원 라이너를 원한다면 포장 풀기를 사용할 수 있습니다.

import random
first_random_item, second_random_item = random.sample(group_of_items, 2)

1
BTW secrets모듈 버전 파이썬 표준 라이브러리 3.6에 추가 된 python.org/dev/peps/pep-0506
and1er

160

색인이 필요한 경우 random.randrange

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

42

Python 3.6부터는 secrets모듈을 사용할 수 있으며 이는 random암호화 또는 보안 용도로 모듈 보다 선호됩니다 .

목록에서 임의의 요소를 인쇄하려면

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

무작위 색인을 인쇄하려면 다음을 수행하십시오.

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

자세한 내용은 PEP 506을 참조하십시오 .


33

목록이 비어있을 때까지 무작위로 선택한 항목을 제거하는 스크립트를 제안합니다.

목록을 비울 때까지 a를 유지하고 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([])

20
또는 당신은 할 수 번 중 반복 처리 그것을 또는 결과를 생성하는 데 팝. "반복없이 무작위로 선택"스트림을 만들면, 처음에 무작위성이 도입 될뿐입니다. random.shufflelist
ShadowRanger

2
이론적 으로는 set 의 pop () 메서드를 사용하여 임의의 요소를 집합에서 제거하고 반환 할 수는 있지만 충분히 무작위 적이지는 않습니다.
Joubarc

14
foo = ['a', 'b', 'c', 'd', 'e']
number_of_samples = 1

파이썬 2에서 :

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

파이썬 3에서 :

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

6
random.choices동안 교체 함께 random.sample교체하지 않고있다.
CentAu

1
또한 random.choices는 이전이 아닌 3.6 이상에서 사용할 수 있습니다!
Cyril N.

11

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'

하나 이상의 items 샘플을 로 반환 array하려면 size인수를 전달하십시오 .

np.random.choice(foo, 5)          # sample with replacement (default)
np.random.choice(foo, 5, False)   # sample without replacement

9

목록에서 항목을 무작위로 선택하는 방법은 무엇입니까?

다음 목록이 있다고 가정하십시오.

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

이 목록에서 무작위로 항목을 검색하는 가장 간단한 방법은 무엇입니까?

정말로 무작위에 가깝기를 원한다면 secrets.choice표준 라이브러리 (Python 3.6의 새로운 기능)에서 제안 합니다.

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

위의 방법은 이전의 권장 사항과 동일합니다 . 파이썬 2에서 초기에 사용할 수 있는 메소드 SystemRandom가있는 random모듈 의 객체를 사용 choice하십시오

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

8

색인이 필요한 경우 다음을 사용하십시오.

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

random.choice가 동일하게 수행합니다.)


2
@tc. 실제로, 그것은 본질적으로 동일합니다. 의 구현은 random.choice(self, seq)입니다 return seq[int(self.random() * len(seq))].
wim

2
@wim 조금 실망 스럽지만 매우 실망스러운 점은 그 정의가 randrange()예를 들어 random.SystemRandom().randrange(3<<51)중대한 편견을 나타내는 것을 의미한다는 것 입니다. 한숨 ..
tc.

6
@ kevinsa5 궁극적으로 float(IEEE double)은 [0,1)에서 한정된 수의 값만 사용할 수 있기 때문 입니다. Random.random()전통적인 방식으로 출력을 생성합니다 : 임의의 정수를 선택 [0, 2**53)하고 나눕니다 2**53(53은 이중 비트 수). 따라서 random()2 ** 53 등가의 복식을 반환하고 N이 2의 거듭 제곱 인 경우에만 이것을 균등하게 N 출력으로 나눌 수 있습니다. 바이어스는 작은 N의 경우 작지만 참조하십시오 collections.Counter(random.SystemRandom().randrange(3<<51)%6 for i in range(100000)).most_common(). (Java의 Random.nextInt ()는 이러한 편견을 피합니다.)
tc.

1
@tc. 나는 2**40(1099511627776 인) 약 미만의 것이 바이어스가 실제로 중요하지 않을 정도로 작을 것이라고 생각합니까? 누군가가 세심하지 않으면 코드 의이 부분에서 문제가 발생할 것으로 기대하지 않을 수 있기 때문에 이것은 문서에서 실제로 지적해야합니다.
Evgeni Sergeev 1:29에

@tc .: 사실, 더 큰 s에 대한 결과를 생성하기 위해 적절한 수의 비트를 얻는 random데 사용 getrandbits합니다 randrange( random.choice또한 사용하고 있습니다). 이것은 2.7과 3.5 모두에 해당됩니다. 사용할 수없는 self.random() * len(seq)경우 에만 사용 getrandbits합니다. 당신이 생각하는 바보 같은 일을하지 않습니다.
ShadowRanger

7

랜덤 인덱스를 정의하는 변수가있는 코드입니다.

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

(파이썬 2.7)


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

1

랜덤 아이템 선택 :

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://stackoverflow.com/a/49682832/4383027의 복제


0

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)

19
왜 지구에 당신이있을 때이 방법을 할 것 random.choice()random.randrange()?
Alexis

"random.choice ()"는 빈 목록에 "IndexError : list index out of range"를 표시합니다.
Abdul Majeed

6
그것이해야 할대로 : 그것은 예외입니다. 빈 목록에서 선택하면 오류가 발생합니다. 리턴 None하면 유효하지 않은 "요소"가 예외를 트리거하는 임의의 나중에 임의의 지점으로 캔을 시작합니다. 또는 더 나쁘게도 예외 대신 잘못된 프로그램이 나타나고 심지어 알지 못합니다.
Alexis

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.