xralf
xralf

Reputation: 3642

random iteration in Python

When you want to iterate sequentially over a list of numbers you will write:

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

But what if you want to iterate over the list of numbers from the range (0..999) randomly? There is a need (in every iteration) to choose randomly the number that wasn't chosen in any previous iteration and there is a need to iterate over all of the numbers from the range (0..999).

Do you know how to do that (smart)?

Upvotes: 49

Views: 84297

Answers (6)

James Scriven
James Scriven

Reputation: 8134

Here's a different approach to iterating a list in random order. This doesn't modify the original list unlike the solutions that use shuffle()

lst=['a','b','c','d','e','f']
for value in sorted(lst,key=lambda _: random.random()):
    print value

or:

for value in random.sample(lst,len(lst)):
    print value

Upvotes: 41

Niklas B.
Niklas B.

Reputation: 95288

You can use random.shuffle() to, well, shuffle a list:

import random

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

By the way, in many cases where you'd use a for loop over a range of integers in other programming languages, you can directly describe the "thing" you want to iterate in Python.
For example, if you want to use the values of i to access elements of a list, you should better shuffle the list directly:

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

NOTE: You should bear the following warning in mind when using random.shuffle() (taken from the docs:

Note that for even rather small len(x), the total number of permutations of x is larger than the period of most random number generators; this implies that most permutations of a long sequence can never be generated.

Upvotes: 53

Oleksandr Shchur
Oleksandr Shchur

Reputation: 356

There is a function random.permutation() in numpy that does exactly that for you. Your code would look like

from numpy.random import permutation

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

Upvotes: 11

leewz
leewz

Reputation: 3346

Demonstrating Python generators and the Fisher–Yates shuffle.

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

You only generate as many random numbers as you use. But honestly, it's probably not saving much, so you should usually use random.shuffle.

Note: If the top card is chosen, deck[i] = deck.pop() would not be safe, so removing the top is done in two steps.

Upvotes: 6

Ned Batchelder
Ned Batchelder

Reputation: 375484

People often miss opportunities for modularization. You can define a function to encapsulate the idea of "iterate randomly":

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

then:

for i in randomly(range(1000)):
    #.. we're good to go ..

Upvotes: 20

Gregor
Gregor

Reputation: 4434

Use the random.shuffle method:

itrange = list(range(100))
random.shuffle(itrange)
for i in itrange:
    print i

Upvotes: 3

Related Questions