Идиома Python Random Slice - PullRequest
       7

Идиома Python Random Slice

6 голосов
/ 29 мая 2011

Есть ли питонический способ нарезать тип последовательности так, чтобы возвращаемый срез имел случайную длину и случайный порядок ? Например, что-то вроде:

>>> l=["a","b","c","d","e"]
>>> rs=l[*:*]
>>> rs
['e','c']

Ответы [ 3 ]

13 голосов
/ 29 мая 2011

Как насчет ...

random.sample(l, random.randint(1, len(l)))

Быстрая ссылка на документы для случайного модуля может быть найдена здесь .

4 голосов
/ 29 мая 2011

Есть тонкое различие, к которому не обращаются ни ваш вопрос, ни другие ответы, поэтому я чувствую, что должен это указать. Это показано на примере ниже.

>>> random.sample(range(10), 5)
[9, 2, 3, 6, 4]
>>> random.sample(range(10)[:5], 5)
[1, 2, 3, 4, 0]

Как видно из выходных данных, первая версия не «разрезает» список, а только пробует его, поэтому возвращаемые значения могут быть откуда угодно в списке. Если вам буквально нужен «фрагмент» списка, то есть если вы хотите ограничить пространство выборки перед выборкой, то следующее не делает то, что вы хотите:

random.sample(l, random.randint(1, len(l)))

Вместо этого вам придется сделать что-то вроде этого:

sample_len = random.randint(1, len(l))
random.sample(l[:sample_len], sample_len)

Но я думаю, что лучший способ сделать это был бы так:

shuffled = l[:random.randint(1, len(l))]
random.shuffle(shuffled)

К сожалению, мне не известна версия shuffle с возвратом копии (т. Е. shuffled сродни sorted).

4 голосов
/ 29 мая 2011

Никакой идиомы, о которой я знаю, но random.sample делает то, что вам нужно.

>>> from random import sample, randint
>>> 
>>> def random_sample(seq):
...     return sample(seq, randint(0, len(seq)))
... 
>>> a = range(0,10)
>>> random_sample(a)
[]
>>> random_sample(a)
[4, 3, 9, 6, 7, 1, 0]
>>> random_sample(a)
[2, 8, 0, 4, 3, 6, 9, 1, 5, 7]
...