Самый питонский способ генерировать случайные строки фиксированной длины из заданных символов - PullRequest
3 голосов
/ 19 января 2012

Это ответвление один из моих предыдущих вопросов

Постановка задачи: если задано число N и произвольный (но не пустой) set / string / list символов E, вернуть случайную строку длины N, состоящую из символы в E.

Какой самый питонический способ сделать это? Я могу пойти с ''.join(( random.choice(E) for i in xrange(N) )), но я ищу лучший способ сделать это. Есть ли в random встроенная функция или, возможно, itertools, которая может это сделать?

Бонусные баллы, если:

  1. Меньше вызовов функций
  2. вставка в одну линию
  3. Лучше обобщаемость для любых N и E
  4. Лучшая производительность во время выполнения

PS : Этот вопрос, на самом деле, заключается только в том, что я являюсь знатоком Python (если можно так сказать) и пытаюсь найти элегантные и художественные способы написания кода. Причина, по которой я упоминаю об этом, заключается в том, что это немного похоже на домашнюю работу, и я хочу заверить SO-сообщество, что это не так.

Ответы [ 2 ]

9 голосов
/ 19 января 2012
''.join(random.sample(E*N, N))

, хотя это не будет работать с сетами, подумайте об этом.Но, честно говоря,

''.join(random.choice(E) for i in xrange(N))

- это уже довольно Pythonic - это просто, ясно и выразительно.

Pythonicness, требующий многочасовой мысли, не является истинной Pythonicness.

4 голосов
/ 19 января 2012

Ваше решение уже выглядит довольно неплохо, но вот несколько вариантов для полноты:

''.join(map(random.choice, [E]*N))

Или с itertools:

from itertools import repeat
''.join(map(random.choice, repeat(E, N)))

Если вы используете Python 2.x, itertools.imap() будет более эффективным, чем map(), поскольку он не создаст полный список в памяти.

Вот некоторые интересные временные данные (проверено на Python 2.6):

>>> import timeit
>>> t1 = timeit.Timer("''.join(random.choice('abcdefghijkl') for i in xrange(3))", "import random")
>>> t2 = timeit.Timer("''.join(map(random.choice, ['abcdefghijkl']*3))", "import random")
>>> t3 = timeit.Timer("''.join(map(random.choice, repeat('abcdefghijkl', 3)))", "import random; from itertools import repeat")
>>> t4 = timeit.Timer("''.join(random.sample('abcdefghijkl'*3, 3))", "import random")
>>> t1.timeit(1000000)   # (random.choice(E) for i in xrange(N))  - OP
7.0744400024414062
>>> t2.timeit(1000000)   # map(random.choice, [E]*N)              - F.J
4.3570120334625244
>>> t3.timeit(1000000)   # map(random.choice, repeat(E, N))       - F.J
5.9411048889160156
>>> t4.timeit(1000000)   # random.sample(E*N, N)                  - DSM
6.9877378940582275

Очевидно, map(random.choice, [E]*N) является победителем, по крайней мере, для маленьких E и N.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...