Методы Python API, которые изменяют структуру на месте, обычно возвращают None, а не измененную структуру данных.
Если вы хотите создать новый случайным образом перетасованный список на основе существующего, где существующий список сохраняется в порядке, вы можете использовать random.sample()с полной длиной ввода:
x = ['foo', 'bar', 'black', 'sheep']
random.sample(x, len(x))
но это вызывает сортировку (операция O (NlogN)), в то время как выборка для входной длины занимает только O (N) операций (тот же процесс, что random.shuffle()и используется, замена случайных значений из сужающегося пула).
Действительно ли keyгарантировано использование функции со случайными значениями ? Некоторые алгоритмы быстрой сортировки не работают, если сравнения не являются самосогласованными. Я вижу, что это работает в любом случае, в зависимости от реализации (decorate-sort-undecorate нужно будет применить keyтолько один раз к каждому элементу, поэтому он будет четко определен).
torek
2
@torek: Python использует decorate-sort-undecorate при сортировке с помощью keyвызываемого объекта. Так что да, это гарантировано, поскольку каждому значению присваивается случайный ключ ровно один раз.
Мартейн Питерс
35
Этот метод тоже работает.
import random
shuffled = random.sample(original, len(original))
Перемешайте последовательность x на место. Необязательный аргумент random - это функция с 0 аргументами, возвращающая случайное число с плавающей запятой в [0.0, 1.0); по умолчанию это функция random ().
>>> x = ['foo','bar','black','sheep']
>>> from random import shuffle
>>> shuffle(x)
>>> x
['bar', 'black', 'sheep', 'foo']
shuffleизменяет список на месте. Это хорошо, потому что копирование большого списка было бы чистыми накладными расходами, если вам больше не нужен исходный список.
2. Питонический стиль
В соответствии с «явно лучше , чем неявное» принцип вещий стиля , возвращая список будет плохая идея, потому что тогда можно было бы подумать , что это новый один , хотя на самом деле это не так .
Но мне это не нравится!
Если вам действительно нужен свежий список, вам нужно будет написать что-то вроде
new_x = list(x) # make a copy
random.shuffle(new_x)
что красиво и ясно. Если вам часто нужна эта идиома, оберните ее в функцию shuffled(см. sorted), Которая возвращает new_x.
Вы можете вернуть перемешанный список, используя, random.sample()как объяснили другие. Он работает, выбирая k элементов из списка без замены . Поэтому, если в вашем списке есть повторяющиеся элементы, они будут обрабатываться однозначно.
Ответы:
random.shuffle()
меняетx
список на место .Методы Python API, которые изменяют структуру на месте, обычно возвращают
None
, а не измененную структуру данных.Если вы хотите создать новый случайным образом перетасованный список на основе существующего, где существующий список сохраняется в порядке, вы можете использовать
random.sample()
с полной длиной ввода:x = ['foo', 'bar', 'black', 'sheep'] random.sample(x, len(x))
Вы также можете использовать
sorted()
withrandom.random()
для ключа сортировки:shuffled = sorted(x, key=lambda k: random.random())
но это вызывает сортировку (операция O (NlogN)), в то время как выборка для входной длины занимает только O (N) операций (тот же процесс, что
random.shuffle()
и используется, замена случайных значений из сужающегося пула).Демо:
>>> import random >>> x = ['foo', 'bar', 'black', 'sheep'] >>> random.sample(x, len(x)) ['bar', 'sheep', 'black', 'foo'] >>> sorted(x, key=lambda k: random.random()) ['sheep', 'foo', 'black', 'bar'] >>> x ['foo', 'bar', 'black', 'sheep']
источник
key
гарантировано использование функции со случайными значениями ? Некоторые алгоритмы быстрой сортировки не работают, если сравнения не являются самосогласованными. Я вижу, что это работает в любом случае, в зависимости от реализации (decorate-sort-undecorate нужно будет применитьkey
только один раз к каждому элементу, поэтому он будет четко определен).key
вызываемого объекта. Так что да, это гарантировано, поскольку каждому значению присваивается случайный ключ ровно один раз.Этот метод тоже работает.
import random shuffled = random.sample(original, len(original))
источник
Согласно документам :
>>> x = ['foo','bar','black','sheep'] >>> from random import shuffle >>> shuffle(x) >>> x ['bar', 'black', 'sheep', 'foo']
источник
Почему на самом деле?
1. Эффективность
shuffle
изменяет список на месте. Это хорошо, потому что копирование большого списка было бы чистыми накладными расходами, если вам больше не нужен исходный список.2. Питонический стиль
В соответствии с «явно лучше , чем неявное» принцип вещий стиля , возвращая список будет плохая идея, потому что тогда можно было бы подумать , что это новый один , хотя на самом деле это не так .
Но мне это не нравится!
Если вам действительно нужен свежий список, вам нужно будет написать что-то вроде
new_x = list(x) # make a copy random.shuffle(new_x)
что красиво и ясно. Если вам часто нужна эта идиома, оберните ее в функцию
shuffled
(см.sorted
), Которая возвращаетnew_x
.источник
У меня был момент аха с такой концепцией:
from random import shuffle x = ['foo','black','sheep'] #original list y = list(x) # an independent copy of the original for i in range(5): print shuffle(y) # shuffles the original "in place" prints "None" return print x,y #prints original, and shuffled independent copy >>> None ['foo', 'black', 'sheep'] ['foo', 'black', 'sheep'] None ['foo', 'black', 'sheep'] ['black', 'foo', 'sheep'] None ['foo', 'black', 'sheep'] ['sheep', 'black', 'foo'] None ['foo', 'black', 'sheep'] ['black', 'foo', 'sheep'] None ['foo', 'black', 'sheep'] ['sheep', 'black', 'foo']
источник
API-интерфейсы Python, которые изменяют структуру на месте, сами возвращают None в качестве вывода.
list = [1,2,3,4,5,6,7,8] print(list)
Вывод: [1, 2, 3, 4, 5, 6, 7, 8]
from random import shuffle print(shuffle(list))
Выход: нет
from random import sample print(sample(list, len(list)))
Вывод: [7, 3, 2, 4, 5, 6, 1, 8]
источник
Вы можете вернуть перемешанный список, используя,
random.sample()
как объяснили другие. Он работает, выбирая k элементов из списка без замены . Поэтому, если в вашем списке есть повторяющиеся элементы, они будут обрабатываться однозначно.>>> l = [1,4,5,3,5] >>> random.sample(l,len(l)) [4, 5, 5, 3, 1] >>> random.sample(l,len(l)-1) [4, 1, 5, 3] >>> random.sample(l,len(l)-1) [3, 5, 5, 1]
источник