Случайная итерация в Python
Если вы хотите последовательно перебирать список чисел, вы будете писать:
for i in range(1000):
# do something with i
Но что, если вы хотите случайным образом перебирать список чисел из диапазона (0..999)? Существует необходимость (на каждой итерации) произвольно выбирать число, которое не было выбрано ни в одной предыдущей итерации, и необходимо перебрать все числа из диапазона (0..999).
Вы знаете, как это сделать (умный)?
Ответы
Ответ 1
Вы можете использовать random.shuffle()
чтобы random.shuffle()
список:
import random
r = list(range(1000))
random.shuffle(r)
for i in r:
# do something with i
Кстати, во многих случаях, когда вы используете цикл for
целого ряда в других языках программирования, вы можете напрямую описать "вещь", которую вы хотите повторить в Python.
Например, если вы хотите использовать значения i
для доступа к элементам списка, вам лучше лучше перетасовать список напрямую:
lst = [1970, 1991, 2012]
random.shuffle(lst)
for x in lst:
print x
ПРИМЕЧАНИЕ: вы должны помнить следующее предупреждение при использовании random.shuffle()
(взято из документации:
Обратите внимание, что даже для довольно небольших len (x) общее число перестановок x больше, чем период большинства генераторов случайных чисел; это означает, что большинство перестановок длинной последовательности никогда не могут быть сгенерированы.
Ответ 2
Люди часто пропускают возможности для модуляции. Вы можете определить функцию для инкапсуляции идеи "итерации случайным образом":
def randomly(seq):
shuffled = list(seq)
random.shuffle(shuffled)
return iter(shuffled)
то
for i in randomly(range(1000)):
#.. we're good to go ..
Ответ 3
Демонстрация генераторов Python и перемешивание Фишера-Йейтса.
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
Вы генерируете столько случайных чисел, сколько используете. Но, честно говоря, это, вероятно, не сильно экономит, поэтому вы должны обычно использовать random.shuffle
.
Примечание. Если выбрана верхняя карта, deck[i] = deck.pop()
будет небезопасной, поэтому удаление верхней осуществляется в два этапа.
Ответ 4
В numpy
есть функция random.permutation()
которая делает именно это для вас. Ваш код будет выглядеть так
from numpy.random import permutation
for i in permutation(1000):
# do something with i
Ответ 5
Используйте метод random.shuffle:
itrange = list(range(100))
random.shuffle(itrange)
for i in itrange:
print i
Ответ 6
Здесь другой подход к итерации списка в случайном порядке. Это не изменяет исходный список в отличие от решений, использующих shuffle()
lst=['a','b','c','d','e','f']
for value in sorted(lst,key=lambda _: random.random()):
print value
или же:
for value in random.sample(lst,len(lst)):
print value