Я хочу вложить цикл десять раз, есть ли лучший способ, чем этот? - PullRequest
2 голосов
/ 07 ноября 2010

Как то так. Я хочу перебрать все символы со словом размером 10

lookup = map(chr, range(32, 127))
for i in lookup:
    for j in lookup:
        for k in lookup:
            for l in lookup:
                for m in lookup:
                    for n in lookup:
                        for o in lookup:
                            for p in lookup:
                                for q in lookup:
                                    for r in lookup:
                                       print(r) # whatever

Вот мои вопросы

1) Есть ли лучший способ?

2) Одна проблема с этим кодом заключается в том, что print (любой из i j k ... r) не работает, вы можете помочь мне разобраться в проблеме? если я даю какую-либо строку, она работает, но не переменные

3) Я пытался сделать то же самое с Perl, даже если там не удалось вывести переменные в цикле, такие как i, j, .. r

Ответы [ 4 ]

15 голосов
/ 07 ноября 2010

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

Очевидно, что вложение десяти циклов - не лучший подход.Я говорю «очевидно», потому что это должно немедленно поднять красный флажок в вашем уме, когда вам нужно скопировать и вставить такой код.Это просто выглядит не очень элегантно, не правда ли?

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

Рекурсивное правило

В нашем случае, как вы генерируете 10-буквенное слово?Допустим, вы уже знаете, как генерировать 9-буквенные слова.Тогда что?

for each 9-letter word:
    for each letter 'A' through 'Z':
        yield word + letter

Должно быть понятно, что это работает одинаково для 9-буквенных слов, 8-буквенных слов и т. Д., С небольшой поправкой к внешнему циклу.В общем, для генерации слов длиной n мы объединяем каждое слово длиной n -1 с каждой буквой алфавита.Или в Python:

import string

def all_words(length):
    for word in all_words(length - 1):
        for letter in string.lowercase:
            yield word + letter

Давайте попробуем запустить его.Начнем с малого.Как насчет всех слов длины 1 для начала?

>>> list(all_words(1))
  File "<stdin>", line 2, in all_words
  File "<stdin>", line 2, in all_words
  File "<stdin>", line 2, in all_words
  File "<stdin>", line 2, in all_words
RuntimeError: maximum recursion depth exceeded

Базовый регистр

Упс, что случилось?О верно.Базовый случай.Чтобы сгенерировать слова длины 2, мы рекурсивно генерируем слова длины 1. Чтобы сгенерировать слова длины 1, мы генерируем слова длины 0. Чтобы сгенерировать слова длины 0, мы генерируем слова длины -1.

Подождите.Какие?Слова длиной -1?Это не имеет смысла.В какой-то момент нам нужно прекратить рекурсию и просто вернуть результат, иначе мы будем рекурсировать вечно.Это базовый случай.Базовый случай - это точка, в которой вам не нужно беспокоиться о повторении, потому что ответ достаточно прост, чтобы сразу понять.

В нашем случае, когда нас просят сгенерировать слова длиной 0,нам действительно не нужно делать тяжелую работу.Вы можете видеть, что единственным «словом» длины 0 является «», пустая строка.Это единственная строка, в которой 0 символов.Поэтому, когда длина равна 0, давайте просто вернем пустую строку:

import string

def all_words(length):
    # Base case
    if length == 0:
        yield ""
    # Recursive rule
    else:
        for word in all_words(length - 1):
            for letter in string.lowercase:
                yield word + letter

ОК, давайте попробуем это снова, не так ли?

>>> list(all_words(2))
['aa', 'ab', 'ac', 'ad', 'ae', 'af', 'ag', 'ah', 'ai', 'aj', 'ak', 'al', 'am', 'an', 'ao', 'ap', 'aq', 'ar', 'as', 'at', 'au', 'av', 'aw', 'ax', 'ay', 'az',
 'ba', 'bb', 'bc', 'bd', 'be', 'bf', 'bg', 'bh', 'bi', 'bj', 'bk', 'bl', 'bm', 'bn', 'bo', 'bp', 'bq', 'br', 'bs', 'bt', 'bu', 'bv', 'bw', 'bx', 'by', 'bz',
 'ca', 'cb', 'cc', 'cd', 'ce', 'cf', 'cg', 'ch', 'ci', 'cj', 'ck', 'cl', 'cm', 'cn', 'co', 'cp', 'cq', 'cr', 'cs', 'ct', 'cu', 'cv', 'cw', 'cx', 'cy', 'cz',
 'da', 'db', 'dc', 'dd', 'de', 'df', 'dg', 'dh', 'di', 'dj', 'dk', 'dl', 'dm', 'dn', 'do', 'dp', 'dq', 'dr', 'ds', 'dt', 'du', 'dv', 'dw', 'dx', 'dy', 'dz',
 'ea', 'eb', 'ec', 'ed', 'ee', 'ef', 'eg', 'eh', 'ei', 'ej', 'ek', 'el', 'em', 'en', 'eo', 'ep', 'eq', 'er', 'es', 'et', 'eu', 'ev', 'ew', 'ex', 'ey', 'ez',
 'fa', 'fb', 'fc', 'fd', 'fe', 'ff', 'fg', 'fh', 'fi', 'fj', 'fk', 'fl', 'fm', 'fn', 'fo', 'fp', 'fq', 'fr', 'fs', 'ft', 'fu', 'fv', 'fw', 'fx', 'fy', 'fz',
 'ga', 'gb', 'gc', 'gd', 'ge', 'gf', 'gg', 'gh', 'gi', 'gj', 'gk', 'gl', 'gm', 'gn', 'go', 'gp', 'gq', 'gr', 'gs', 'gt', 'gu', 'gv', 'gw', 'gx', 'gy', 'gz',
 'ha', 'hb', 'hc', 'hd', 'he', 'hf', 'hg', 'hh', 'hi', 'hj', 'hk', 'hl', 'hm', 'hn', 'ho', 'hp', 'hq', 'hr', 'hs', 'ht', 'hu', 'hv', 'hw', 'hx', 'hy', 'hz',
 'ia', 'ib', 'ic', 'id', 'ie', 'if', 'ig', 'ih', 'ii', 'ij', 'ik', 'il', 'im', 'in', 'io', 'ip', 'iq', 'ir', 'is', 'it', 'iu', 'iv', 'iw', 'ix', 'iy', 'iz',
 'ja', 'jb', 'jc', 'jd', 'je', 'jf', 'jg', 'jh', 'ji', 'jj', 'jk', 'jl', 'jm', 'jn', 'jo', 'jp', 'jq', 'jr', 'js', 'jt', 'ju', 'jv', 'jw', 'jx', 'jy', 'jz',
 'ka', 'kb', 'kc', 'kd', 'ke', 'kf', 'kg', 'kh', 'ki', 'kj', 'kk', 'kl', 'km', 'kn', 'ko', 'kp', 'kq', 'kr', 'ks', 'kt', 'ku', 'kv', 'kw', 'kx', 'ky', 'kz',
 'la', 'lb', 'lc', 'ld', 'le', 'lf', 'lg', 'lh', 'li', 'lj', 'lk', 'll', 'lm', 'ln', 'lo', 'lp', 'lq', 'lr', 'ls', 'lt', 'lu', 'lv', 'lw', 'lx', 'ly', 'lz',
 'ma', 'mb', 'mc', 'md', 'me', 'mf', 'mg', 'mh', 'mi', 'mj', 'mk', 'ml', 'mm', 'mn', 'mo', 'mp', 'mq', 'mr', 'ms', 'mt', 'mu', 'mv', 'mw', 'mx', 'my', 'mz',
 'na', 'nb', 'nc', 'nd', 'ne', 'nf', 'ng', 'nh', 'ni', 'nj', 'nk', 'nl', 'nm', 'nn', 'no', 'np', 'nq', 'nr', 'ns', 'nt', 'nu', 'nv', 'nw', 'nx', 'ny', 'nz',
 'oa', 'ob', 'oc', 'od', 'oe', 'of', 'og', 'oh', 'oi', 'oj', 'ok', 'ol', 'om', 'on', 'oo', 'op', 'oq', 'or', 'os', 'ot', 'ou', 'ov', 'ow', 'ox', 'oy', 'oz',
 'pa', 'pb', 'pc', 'pd', 'pe', 'pf', 'pg', 'ph', 'pi', 'pj', 'pk', 'pl', 'pm', 'pn', 'po', 'pp', 'pq', 'pr', 'ps', 'pt', 'pu', 'pv', 'pw', 'px', 'py', 'pz',
 'qa', 'qb', 'qc', 'qd', 'qe', 'qf', 'qg', 'qh', 'qi', 'qj', 'qk', 'ql', 'qm', 'qn', 'qo', 'qp', 'qq', 'qr', 'qs', 'qt', 'qu', 'qv', 'qw', 'qx', 'qy', 'qz',
 'ra', 'rb', 'rc', 'rd', 're', 'rf', 'rg', 'rh', 'ri', 'rj', 'rk', 'rl', 'rm', 'rn', 'ro', 'rp', 'rq', 'rr', 'rs', 'rt', 'ru', 'rv', 'rw', 'rx', 'ry', 'rz',
 'sa', 'sb', 'sc', 'sd', 'se', 'sf', 'sg', 'sh', 'si', 'sj', 'sk', 'sl', 'sm', 'sn', 'so', 'sp', 'sq', 'sr', 'ss', 'st', 'su', 'sv', 'sw', 'sx', 'sy', 'sz',
 'ta', 'tb', 'tc', 'td', 'te', 'tf', 'tg', 'th', 'ti', 'tj', 'tk', 'tl', 'tm', 'tn', 'to', 'tp', 'tq', 'tr', 'ts', 'tt', 'tu', 'tv', 'tw', 'tx', 'ty', 'tz',
 'ua', 'ub', 'uc', 'ud', 'ue', 'uf', 'ug', 'uh', 'ui', 'uj', 'uk', 'ul', 'um', 'un', 'uo', 'up', 'uq', 'ur', 'us', 'ut', 'uu', 'uv', 'uw', 'ux', 'uy', 'uz',
 'va', 'vb', 'vc', 'vd', 've', 'vf', 'vg', 'vh', 'vi', 'vj', 'vk', 'vl', 'vm', 'vn', 'vo', 'vp', 'vq', 'vr', 'vs', 'vt', 'vu', 'vv', 'vw', 'vx', 'vy', 'vz',
 'wa', 'wb', 'wc', 'wd', 'we', 'wf', 'wg', 'wh', 'wi', 'wj', 'wk', 'wl', 'wm', 'wn', 'wo', 'wp', 'wq', 'wr', 'ws', 'wt', 'wu', 'wv', 'ww', 'wx', 'wy', 'wz',
 'xa', 'xb', 'xc', 'xd', 'xe', 'xf', 'xg', 'xh', 'xi', 'xj', 'xk', 'xl', 'xm', 'xn', 'xo', 'xp', 'xq', 'xr', 'xs', 'xt', 'xu', 'xv', 'xw', 'xx', 'xy', 'xz',
 'ya', 'yb', 'yc', 'yd', 'ye', 'yf', 'yg', 'yh', 'yi', 'yj', 'yk', 'yl', 'ym', 'yn', 'yo', 'yp', 'yq', 'yr', 'ys', 'yt', 'yu', 'yv', 'yw', 'yx', 'yy', 'yz',
 'za', 'zb', 'zc', 'zd', 'ze', 'zf', 'zg', 'zh', 'zi', 'zj', 'zk', 'zl', 'zm', 'zn', 'zo', 'zp', 'zq', 'zr', 'zs', 'zt', 'zu', 'zv', 'zw', 'zx', 'zy', 'zz']

Круто.

10 голосов
/ 07 ноября 2010

itertools - ваш друг.

>>> lookup = map(chr, range(32, 127))
>>> import itertools
>>> itertools.permutations(lookup, 10)
<itertools.permutations object at 0x023C8AE0>

Обратите внимание, что permutations даст вам каждое слово, тогда как combinations даст вам каждую группу различных символов.Также обратите внимание, что существует лот десятибуквенных слов.

1 голос
/ 07 ноября 2010

Я также прочитал «Девять миллиардов имен Бога», но я не думаю, что он закончится, когда твоя программа закончится!

Если серьезно, ваш код будет довольно быстрым и простым. если вы помещаете результаты в массив (или строку), вы создаете индекс, который указывает на текущий уровень, а затем для каждого цикла просто увеличиваете индекс. Когда уровень закончен, уменьшите его, чтобы «вернуться». Это решение не будет таким ясным, но оно будет динамичным, т.е. Вы можете выбрать количество уровней во время выполнения.

0 голосов
/ 07 ноября 2010
import itertools

lookup = map(chr, range(32, 127))

for i in itertools.product(lookup, repeat=10):
    print i

но у вас будет как ( Редактировать ) цикл 96 ^ 10 так ???

...