2014-09-18 3 views
1

Для недавнего скрипта мне пришлось перебирать возможные потоки через ветвящееся дерево. Я построил словарь, который будет содержать состояние запуска для каждого элемента, чтобы я мог его оценить. Например:Сокращение вложенных циклов, которые строят словари/строки (стиль ветвящегося дерева)

for a in range(0, 2): 
    for b in range(0, 2): 
    for c in range(0, 2): 
     for d in range(0, 2): 
     ... 
     run = [a,b,c,d ...] 

К сожалению, это началось с малого, но выросло до более дюжины штатов. Как это можно свести к устранению всех вложенных циклов?

Будет ли подобный ответ отличаться, если в некоторых из состояний было 3 или 4 состояния вместо 2?

Аналогично, как будет затронута одна и та же проблема, если каждый цикл был из списка функций? Я подозревал, что все будет так. Например:

def leet_lookup(char): 
    table = {"a": ["a","A","@"], 
      "b": ["b", "B", "8"], 
      "c": ["c", "C", "<"], 
      "e": ["e", "E", "3"], 
      "i": ["i", "I", "1"], 
      "l": ["l", "L", "1"], 
      "o": ["o", "O", "0"], 
      "t": ["t", "T", "7"] } 
    try: 
     result = table[char.lower()] 
    except KeyError: 
     result = [char.lower(), char.upper()] 
    return result 

result = [] 
# V o l l e y b a l l = 10 chars 
for c1 in leet_lookup('v'): 
    for c2 in leet_lookup('o'): 
    for c3 in leet_lookup('l'): 
     for c4 in leet_lookup('l'): 
     for c5 in leet_lookup('e'): 
      for c6 in leet_lookup('y'): 
      for c7 in leet_lookup('b'): 
       for c8 in leet_lookup('a'): 
       for c9 in leet_lookup('l'): 
        for c10 in leet_lookup('l'): 
        result.append("%s%s%s%s%s%s%s%s%s%s" % (c1, c2, c3, c4, c5, c6, c7, c8, c9, c10)) 

ответ

3

Еще раз, это проблема, выпрашивая решения от itertools.

Для первой проблемы просто используйте product.

from itertools import product 
for run in product(range(2), repeat=5): 
    print(run) 

# (0, 0, 0, 0, 0) 
# (0, 0, 0, 0, 1) 
# (0, 0, 0, 1, 0) 
# etc. 

Если у вас есть состояния на индикаторе, либо а) каждый индикатор имеет такое же число состояний, и вы можете просто изменить аргумент range, или б) различные показатели имеют разное число состояний, в этом случае вы можете сделать что-то похожее на ответ ниже, заменив вызов leet_lookuprange и имея список номеров состояний вместо lookups.

Для второго, вы, вероятно, захотите создать список итераций, которые вы можете использовать product.

lookups = ['v', 'o', 'l', 'l'] 
items = [leet_lookup(a) for a in lookups] 
for c in product(*items): 
    print(c) 

# ('v', 'o', 'l', 'l') 
# ('v', 'o', 'l', 'L') 
# ('v', 'o', 'l', '1') 
# ('v', 'o', 'L', 'l') 
# etc. 

В общем, если вы когда-нибудь есть проблема, которая включает в себя какой-либо комбинации или трансформации итераторы, вы должны сначала искать itertools функции или recipe.

+0

приятно Тхо решение! – soupault

+0

Отличный ответ и совет, второй был особенно сложным, но ваше решение отлично! Спасибо –

0

Вы хотите, чтобы все перестановки между всеми table словарных значений, так что вы можете использовать itertools модуль для поиска, что, который больше вещий и map и join функции, чтобы объединить их!

import itertools 
table = {"a": ["a","A","@"], 
     "b": ["b", "B", "8"], 
     "c": ["c", "C", "<"], 
     "e": ["e", "E", "3"], 
     "i": ["i", "I", "1"], 
     "l": ["l", "L", "1"], 
     "o": ["o", "O", "0"], 
     "t": ["t", "T", "7"] } 

for pro in itertools.product(table['a'],table['b'],table['c'],table['e'],table['i'],table['l'],table['o'],table['t']): 
    print ''.join(pro) 

некоторые выхода:

@8<3Il0T 
@8<3Il07 
@8<3ILot 
@8<3ILoT 
@8<3ILo7 
@8<3ILOt 
@8<3ILOT 
@8<3ILO7 
@8<3IL0t 
... 
+0

Спасибо за решение. Тем не менее, это, как представляется, делает только каждую перестановку символов внутри таблицы и не работает с предоставленной строкой по мере необходимости. –

Смежные вопросы