Wie wähle ich zufällig ein Element aus einer Liste aus?

1759

Angenommen, ich habe die folgende Liste:

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

Was ist der einfachste Weg, um ein Element zufällig aus dieser Liste abzurufen?

Strahl
quelle

Antworten:

2677

Verwenden random.choice()

import random

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

Für kryptografisch sichere zufällige Auswahlmöglichkeiten (z. B. zum Generieren einer Passphrase aus einer Wortliste) verwendensecrets.choice()

import secrets

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

secretsist neu in Python 3.6, in älteren Versionen von Python können Sie die random.SystemRandomKlasse verwenden:

import random

secure_random = random.SystemRandom()
print(secure_random.choice(foo))
Pēteris Caune
quelle
3
Erhalten zwei aufeinanderfolgende Rückrufe random.choice(foo)zwei unterschiedliche Ergebnisse?
Eduardo Pignatelli
34
@EduardoPignatelli Jede Wahl ist zufällig, so dass es können zwei unterschiedliche Ergebnisse zurückgeben, aber je nach dem Start Samen, es ist nicht garantiert. Wenn Sie n verschiedene zufällige Elemente aus einer Liste zuerst auswählen möchten , verwenden Sierandom.sample(lst, n)
Graham
6
in einem verwandten Hinweis, Standard pseudo-random generators are not suitable for security/cryptographic purposes. ref
Xiao
184

Wenn Sie mehr als ein Element zufällig aus einer Liste auswählen oder ein Element aus einem Satz auswählen möchten, würde ich empfehlen, random.samplestattdessen zu verwenden.

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] 

Wenn Sie jedoch nur ein einzelnes Element aus einer Liste ziehen, ist die Auswahl weniger umständlich, da die Verwendung von sample die Syntax random.sample(some_list, 1)[0]anstelle von verwenden würde random.choice(some_list).

Leider funktioniert die Auswahl nur für eine einzelne Ausgabe von Sequenzen (wie Listen oder Tupeln). Dies random.choice(tuple(some_set))kann jedoch eine Option sein, um einen einzelnen Artikel aus einem Set zu erhalten.

BEARBEITEN: Verwenden von Geheimnissen

Wie viele bereits betont haben, sollten Sie das Modul "Geheimnisse" verwenden, wenn Sie sicherere Pseudozufallsstichproben benötigen:

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]

EDIT: Pythonic One-Liner

Wenn Sie einen pythonischeren Einzeiler für die Auswahl mehrerer Elemente wünschen, können Sie das Auspacken verwenden.

import random
first_random_item, second_random_item = random.sample(group_of_items, 2)
Paul
quelle
1
Das BTW- secretsModul wurde der Python-Standardbibliothek in Version 3.6 hinzugefügt. Python.org/dev/peps/pep-0506
und
160

Wenn Sie auch den Index benötigen, verwenden Sie random.randrange

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

Ab Python 3.6 können Sie das secretsModul verwenden, das dem randomModul für Kryptografie- oder Sicherheitszwecke vorzuziehen ist .

So drucken Sie ein zufälliges Element aus einer Liste:

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

So drucken Sie einen zufälligen Index:

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

Einzelheiten finden Sie in PEP 506 .

Chris_Rands
quelle
33

Ich schlage ein Skript vor, um zufällig ausgewählte Elemente von einer Liste zu entfernen, bis sie leer sind:

Pflegen Sie ein setund entfernen Sie zufällig aufgenommenes Element (mit choice), bis die Liste leer ist.

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

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

Drei Läufe geben drei verschiedene Antworten:

>>> 
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([])
kiriloff
quelle
20
Oder Sie könnten nur random.shuffledie listeinmal und entweder Iterierte es oder Pop es Ergebnisse zu produzieren. Beides würde zu einem vollkommen adäquaten Stream "Zufällig ohne Wiederholungen auswählen" führen, nur dass die Zufälligkeit am Anfang eingeführt würde.
ShadowRanger
2
Theoretisch können Sie die pop () -Methode einer Menge verwenden, um ein beliebiges Element aus einer Menge zu entfernen und zurückzugeben, aber es ist wahrscheinlich nicht zufällig genug.
Joubarc
14
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)
Fardin
quelle
6
Beachten Sie, dass random.choicesmit Ersatz, während random.sampleohne Ersatz ist.
CentAu
1
Beachten Sie auch, dass random.choices ab Version 3.6 verfügbar ist, nicht vorher!
Cyril N.
11

numpy Lösung: numpy.random.choice

Für diese Frage funktioniert sie genauso wie die akzeptierte Antwort ( import random; random.choice()), aber ich habe sie hinzugefügt, da der Programmierer möglicherweise bereits importiert hat numpy(wie ich) und es auch einige Unterschiede zwischen den beiden Methoden gibt , die Ihren tatsächlichen Anwendungsfall betreffen können.

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

Für die Reproduzierbarkeit können Sie Folgendes tun:

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

Übergeben Sie für Beispiele eines oder mehrerer Elemente , die als zurückgegeben werden array, das folgende sizeArgument:

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

Wie wähle ich zufällig ein Element aus einer Liste aus?

Angenommen, ich habe die folgende Liste:

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

Was ist der einfachste Weg, um ein Element zufällig aus dieser Liste abzurufen?

Wenn Sie nahezu zufällig sein möchten , empfehle ich secrets.choiceaus der Standardbibliothek (Neu in Python 3.6.):

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

Das Obige entspricht meiner früheren Empfehlung, ein SystemRandomObjekt aus dem randomModul mit der choiceMethode zu verwenden - früher in Python 2 verfügbar:

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

Und nun:

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

Wenn Sie eine deterministische Pseudozufallsauswahl wünschen, verwenden Sie die choiceFunktion (die eigentlich eine gebundene Methode für ein RandomObjekt ist):

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

Es scheint zufällig zu sein, aber es ist tatsächlich nicht so, was wir sehen können, wenn wir es wiederholt neu aussäen:

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

Ein Kommentar:

Hier geht es nicht darum, ob random.choice wirklich zufällig ist oder nicht. Wenn Sie den Samen reparieren, erhalten Sie reproduzierbare Ergebnisse - und dafür ist der Samen ausgelegt. Sie können auch einen Startwert an SystemRandom übergeben.sr = random.SystemRandom(42)

Ja, Sie können ein "Seed" -Argument übergeben, aber Sie werden sehen, dass das SystemRandomObjekt es einfach ignoriert :

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

Wenn Sie den Index benötigen, verwenden Sie einfach:

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

random.choice macht das gleiche :)

Janek Olszak
quelle
2
@tc. Eigentlich macht es im Wesentlichen das gleiche. Implementierung von random.choice(self, seq)is return seq[int(self.random() * len(seq))].
wim
2
@wim Das ist ein wenig enttäuschend, aber das sehr Enttäuschende ist, dass die Definition auch randrange()bedeutet, dass z random.SystemRandom().randrange(3<<51). B. eine signifikante Verzerrung vorliegt. Seufz ...
tc.
6
@ kevinsa5 Letztendlich liegt es daran, dass a float(ein IEEE-Double) nur eine endliche Anzahl von Werten in [0,1] annehmen kann. Random.random()generiert seine Ausgabe auf herkömmliche Weise: Wählen Sie eine zufällige Ganzzahl aus [0, 2**53)und dividieren Sie durch 2**53(53 ist die Anzahl der Bits in einem Doppel). Es werden also random()2 ** 53 gleichwahrscheinliche Doppelte zurückgegeben, und Sie können dies nur dann gleichmäßig in N Ausgänge aufteilen, wenn N eine Potenz von 2 ist. Die Vorspannung ist für kleine N klein, aber siehe collections.Counter(random.SystemRandom().randrange(3<<51)%6 for i in range(100000)).most_common(). (Javas Random.nextInt () vermeidet solche Verzerrungen.)
tc.
1
@tc. Ich nehme an, etwas weniger als ungefähr 2**40(das ist 1099511627776) wäre klein genug, damit die Tendenz in der Praxis keine Rolle spielt? Dies sollte in der Dokumentation unbedingt erwähnt werden, da jemand, der nicht genau ist, möglicherweise keine Probleme mit diesem Teil seines Codes erwartet.
Evgeni Sergeev
@tc .: Eigentlich randomAnwendungen , getrandbitsum eine ausreichende Anzahl von Bits zu erhalten , um ein Ergebnis für eine größere zu erzeugen randranges ( random.choiceist auch mit, dass). Dies gilt sowohl für 2.7 als auch für 3.5. Es wird nur verwendet, self.random() * len(seq)wenn getrandbitses nicht verfügbar ist. Es macht nicht das Dumme, was du denkst.
ShadowRanger
7

Dies ist der Code mit einer Variablen, die den Zufallsindex definiert:

import random

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

Dies ist der Code ohne die Variable:

import random

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

Und dies ist der Code auf kürzeste und intelligenteste Weise:

import random

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

(Python 2.7)

Liam
quelle
3

Der folgende Code zeigt, ob Sie dieselben Artikel produzieren müssen. Sie können auch angeben, wie viele Samples Sie extrahieren möchten.
Die sampleMethode gibt eine neue Liste mit Elementen aus der Grundgesamtheit zurück, während die ursprüngliche Grundgesamtheit unverändert bleibt. Die resultierende Liste befindet sich in Auswahlreihenfolge, sodass alle Unterschnitte auch gültige Zufallsstichproben sind.

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']
Memin
quelle
1

Zufällige Artikelauswahl:

import random

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

new_list = random.sample(my_list, num_selections)

Um die Reihenfolge der Liste beizubehalten, können Sie Folgendes tun:

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

Duplikat von https://stackoverflow.com/a/49682832/4383027

Solomon Vimal
quelle
0

Wir können dies auch mit Randint tun.

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)
Abdul Majeed
quelle
19
Warum um alles in der Welt würdest du es so machen, wenn es random.choice()und gibt random.randrange()?
Alexis
"random.choice ()" gibt Ihnen "IndexError: Listenindex außerhalb des Bereichs" auf einer leeren Liste.
Abdul Majeed
6
Wie es sollte: Dafür gibt es Ausnahmen. Die Auswahl aus einer leeren Liste ist ein Fehler. Wenn Sie Nonedie Dose zurückgeben, wird die Dose an einen zufälligen späteren Punkt verschoben, an dem das ungültige "Element" eine Ausnahme auslöst. oder noch schlimmer, Sie erhalten ein falsches Programm anstelle einer Ausnahme, und Sie wissen es nicht einmal.
Alexis
0

Sie könnten einfach:

from random import randint

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

print(foo[randint(0,4)])
Evan Schwartzentruber
quelle