Reputation: 3642
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
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
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
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
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
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
Reputation: 4434
Use the random.shuffle method:
itrange = list(range(100))
random.shuffle(itrange)
for i in itrange:
print i
Upvotes: 3