Listeden rastgele bir öğe nasıl seçilir?


1759

Aşağıdaki listeye sahip olduğumu varsayın:

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

Bu listeden rastgele bir öğe almanın en basit yolu nedir?

Yanıtlar:


2677

kullanım random.choice()

import random

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

İçin şifreli olarak güvenli rasgele seçimler (örneğin bir wordlist bir parola oluşturmak için) kullanımısecrets.choice()

import secrets

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

secretsPython 3.6'da yeni, Python'un eski sürümlerinde random.SystemRandomsınıfı kullanabilirsiniz :

import random

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

3
İki ardışık random.choice(foo)geri dönüş çağrısı yapmak iki farklı sonuç getirir mi?
Eduardo Pignatelli

34
O kadar @EduardoPignatelli Her seçim, rastgele olabilir iki farklı sonuçlar döndürebilir, ancak başlangıç tohum bağlı olarak, garanti değil. Eğer seçmek istiyorsanız , n bir liste farklı rasgele elemanları lst , kullanımrandom.sample(lst, n)
Graham

6
ilgili bir notta, Standard pseudo-random generators are not suitable for security/cryptographic purposes. ref
Xiao

184

Bir listeden birden fazla öğeyi rastgele seçmek veya bir kümeden bir öğe seçmek istiyorsanız, random.samplebunun yerine kullanmanızı öneririm .

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] 

Ancak listeden yalnızca tek bir öğe çekiyorsanız, seçim yapmak daha az karmaşıktır, çünkü örnek kullanmak random.sample(some_list, 1)[0]yerine sözdizimi olacaktır random.choice(some_list).

Ne yazık ki, seçim sadece sekanslardan (listeler veya tuples gibi) tek bir çıktı için çalışır. Rağmen random.choice(tuple(some_set))bir kümeden tek bir öğe almak için bir seçenek olabilir.

EDIT: Sırları Kullanma

Birçoğunun işaret ettiği gibi, daha güvenli sahte örneklere ihtiyacınız varsa, sırlar modülünü kullanmalısınız:

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]

DÜZENLEME: Pitonik Tek Katlı

Birden fazla öğe seçmek için daha pythonic bir astar istiyorsanız, ambalajı açmayı kullanabilirsiniz.

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

1
secrets3.6 sürümünde Python standart kütüphanesine BTW modülü eklendi python.org/dev/peps/pep-0506
and1er

160

Dizine de ihtiyacınız varsa, random.randrange

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

42

Python 3.6'dan itibaren, şifreleme veya güvenlik kullanımları için modüle secretstercih edilen modülü kullanabilirsiniz random.

Listeden rastgele bir öğe yazdırmak için:

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

Rastgele bir dizin yazdırmak için:

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

Ayrıntılar için, bkz. PEP 506 .


33

Boş olana kadar bir listeden rastgele alınan öğeleri kaldırmak için bir komut dosyası öneriyorum:

A işaretini koruyun setve choiceliste boşalana kadar rastgele alınan öğeyi (ile ) kaldırın .

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

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

Üç koşu üç farklı cevap verir:

>>> 
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
Yoksa tekini kez ve ya yinelemeyi o veya sonuçları üretmek için pop. Her ikisi de mükemmel bir şekilde yeterli "tekrar olmadan rastgele seç" akışı ile sonuçlanır, sadece rastgele başlangıçta tanıtılacaktı. random.shufflelist
ShadowRanger

2
Teorik olarak , bir kümeden isteğe bağlı bir öğeyi kaldırmak ve döndürmek için bir kümenin pop () yöntemini kullanabilirsiniz , ancak muhtemelen yeterince rasgele değildir.
Joubarc

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

Python 2'de:

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

Python 3'te:

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

6
random.choicesDeğişim sırasında yedek olduğunu unutmayın random.sample.
CentAu

1
Ayrıca random.choices'in 3.6 ve sonrasında kullanılabilir olduğunu unutmayın, daha önce değil!
Cyril

11

numpy çözüm: numpy.random.choice

Bu soru için, kabul edilen cevapla aynı şekilde çalışır ( import random; random.choice()), ancak ekledim çünkü programcı numpyzaten (benim gibi) içe aktarmış olabilir ve ayrıca iki yöntem arasında gerçek kullanım durumunuzu ilgilendirebilecek bazı farklılıklar var .

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

Tekrarlanabilirlik için şunları yapabilirsiniz:

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

Olarak döndürülen bir veya daha fazla öğenin örnekleri arrayiçin şu sizeargümanı iletin:

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

9

Listeden rastgele bir öğe nasıl seçilir?

Aşağıdaki listeye sahip olduğumu varsayın:

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

Bu listeden rastgele bir öğe almanın en basit yolu nedir?

Eğer gerçekten rastgele yakın istiyorsanız , o zaman ben secrets.choicestandart kütüphaneden (Python 3.6 Yeni.) Öneririz:

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

Yukarıda Python 2'de daha önce mevcut olan yöntemle modülden bir SystemRandomnesne kullanarak önceki tavsiyemle eşdeğerdir :randomchoice

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

Ve şimdi:

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

Deterministik bir sözde seçim istiyorsanız, choiceişlevi kullanın (aslında bir Randomnesne üzerinde bağlı bir yöntemdir ):

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

Rastgele gibi görünüyor, ancak aslında tekrar tekrar yeniden kalıplayıp tekrarlayamadığımızı görebileceğimiz aslında değil:

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

Bir yorum:

Bu random.choice gerçekten rastgele olup olmadığı ile ilgili değildir. Tohumu sabitlerseniz, tekrarlanabilir sonuçlar elde edersiniz - ve bu tohum için tasarlanmıştır. Bir tohumu SystemRandom'a da iletebilirsiniz.sr = random.SystemRandom(42)

Evet, bunu bir "tohum" argümanı olarak iletebilirsiniz, ancak SystemRandomnesnenin bunu görmezden geldiğini göreceksiniz :

def seed(self, *args, **kwds):
    "Stub method.  Not used for a system random number generator."
    return None

8

Eğer dizine ihtiyacınız varsa kullanın:

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

random.choice aynı şeyi yapıyor :)


2
@tc. Aslında, aynı şeyi yapıyor. Uygulanması random.choice(self, seq)DİR return seq[int(self.random() * len(seq))].
wim

2
@wim Bu biraz hayal kırıklığı yaratıyor, ama çok hayal kırıklığı yaratan şey de bunun tanımının, randrange()örneğin random.SystemRandom().randrange(3<<51)önemli önyargı sergilediği anlamına geliyor . Ah ...
tc.

6
@ kevinsa5 Nihayetinde bir float(IEEE double) sadece [0,1] 'de sınırlı sayıda değer alabilir. Random.random()çıktısını geleneksel şekilde üretir: rastgele bir tamsayı seçin [0, 2**53)ve bölün 2**53(53, bir çiftteki bit sayısıdır). Yani random()2 ** 53 eşdeğeri iki katına çıkar ve bunu N çıkış 2'ye eşitse N çıkışlarına eşit olarak bölebilirsiniz. Sapma küçük N için küçüktür, ama bkz collections.Counter(random.SystemRandom().randrange(3<<51)%6 for i in range(100000)).most_common(). (Java'nın Random.nextInt () yöntemi bu önyargıyı önler.)
tc.

1
@tc. Sanırım yaklaşık 2**401099511627776'dan daha az bir şey , uygulamada önyargının önemli olmayacağı kadar küçük olurdu? Bu gerçekten belgelerde belirtilmelidir, çünkü eğer birisi titiz değilse, kodlarının bu kısmından sorun çıkmasını beklemeyebilirler.
Evgeni Sergeev

@tc .: Aslında randomkullanımları getrandbitsdaha büyük bir sonuç üretmek için bitlerin uygun bir sayısını almak için randranges ( random.choiceAyrıca kullanarak). Bu hem 2.7 hem de 3.5 için geçerlidir. Sadece kullandığı self.random() * len(seq)zaman getrandbitskullanılamaz. Düşündüğün aptalca şeyi yapmıyor.
ShadowRanger

7

Rastgele dizini tanımlayan bir değişkene sahip kod:

import random

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

Bu değişken olmayan koddur:

import random

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

Ve bu, kodu en kısa ve en akıllı şekilde yapar:

import random

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

(python 2.7)


3

Aşağıdaki kod, aynı öğeleri üretmeniz gerekip gerekmediğini gösterir. Ayrıca kaç tane numune almak istediğinizi de belirtebilirsiniz. Yöntem değişmeden orijinal nüfus bırakırken popülasyondan elemanları içeren yeni bir listesini verir. Sonuçta elde edilen liste seçim sırasına göre tüm alt dilimlerin geçerli rasgele örnekler olmasını sağlar.
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

Rastgele öğe seçimi:

import random

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

new_list = random.sample(my_list, num_selections)

Listenin sırasını korumak için şunları yapabilirsiniz:

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

Kopyası https://stackoverflow.com/a/49682832/4383027


0

Bunu randint kullanarak da yapabiliriz.

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
Neden yeryüzünde varken o, bu şekilde yapacağını random.choice()ve random.randrange()?
alexis

"random.choice ()" size boş listede "IndexError: liste dizini aralık dışında" verecektir.
Abdul Majeed

6
Olması gerektiği gibi: istisnalar bunun içindir. Boş bir listeden seçim yapmak bir hatadır. Döndürme, Nonekutuyu geçersiz "öğenin" bir istisnayı tetiklediği rastgele bir sonraki noktaya vurur; veya daha da kötüsü, bir istisna yerine yanlış bir program alıyorsunuz ve bunu bile bilmiyorsunuz.
alexis

0

Şunları yapabilirsiniz:

from random import randint

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

print(foo[randint(0,4)])
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.