itération aléatoire en Python

quand vous voulez itérer séquentiellement sur une liste de nombres vous écrirez:

for i in range(1000):
  # do something with i

mais que faire si vous voulez itérer sur la liste des nombres de la gamme (0..999) au hasard? Il y a un besoin (dans chaque itération) de choisir au hasard le nombre qui n'a pas été choisi dans une itération précédente et il y a un besoin d'itérer sur tous les nombres de la gamme (0..999).

savez-vous faire cela (smart)?

18
demandé sur xralf 2012-02-13 00:26:43

5 réponses

Vous pouvez utiliser random.shuffle(), eh bien, shuffle une liste:

import random

r = list(range(1000))
random.shuffle(r)
for i in r:
  # do something with i

soit dit en passant, dans de nombreux cas où vous utiliseriez un for boucle sur une gamme d'entiers dans d'autres langages de programmation, vous pouvez décrire directement la "chose" que vous voulez itérer en Python.

Par exemple, si vous souhaitez utiliser les valeurs de i pour accéder aux éléments d'une liste, vous devriez mieux shuffle directement la liste:

lst = [1970, 1991, 2012]
random.shuffle(lst)
for x in lst:
  print x

NOTE: vous devez supporter l'avertissement suivant à l'esprit lors de l'utilisation de random.shuffle() (prises à partir de la docs:

notez que pour des len(x) même assez petits, le nombre total de les permutations de x est plus grande que la période de la plupart des nombres aléatoires générateurs; ceci implique que la plupart des permutations d'une longue séquence peuvent ne jamais être généré.

25
répondu Niklas B. 2017-07-24 19:51:15

les gens ratent souvent des occasions de modularisation. Vous pouvez définir une fonction pour encapsuler l'idée de "itérer au hasard":

def randomly(seq):
    shuffled = list(seq)
    random.shuffle(shuffled)
    return iter(shuffled)

puis:

for i in randomly(range(1000)):
    #.. we're good to go ..
15
répondu Ned Batchelder 2012-02-12 22:37:10

Démonstration de Python et des générateurs de l' shuffle de Fisher–Yates.

import random

def shuffled(sequence):
    deck = list(sequence)
    while len(deck):
        i = random.randint(0, len(deck) - 1) # choose random card
        card = deck[i]                       # take the card
        deck[i] = deck[-1]                   # put top card in its place
        deck.pop()                           # remove top card
        yield card

vous générez seulement autant de nombres aléatoires que vous utilisez. Mais honnêtement, il est probablement pas économiser beaucoup, donc vous devriez généralement utiliser random.shuffle.

Remarque: Si la première carte est choisie, deck[i] = deck.pop() ne serait pas sûr, donc enlever le haut est fait en deux étapes.

6
répondu leewz 2016-01-13 02:07:55

Il existe une fonction random.permutation()numpy Cela fait exactement cela pour vous. Votre code ressemblerait à

from numpy.random import permutation

for i in permutation(1000):
    # do something with i
4
répondu Alexander Shchur 2016-03-13 14:34:44

Utilisez le hasard.shuffle méthode:

itrange = list(range(100))
random.shuffle(itrange)
for i in itrange:
    print i
3
répondu Gregor 2012-02-12 20:29:17