2016-08-23 3 views
4

Учитывая список верхних пределов: B1, B2, .. BN;
Функции зависимостей: f1, ..., Fn-1,Использование itertools для произвольного количества вложенных циклов разных диапазонов с зависимостями?

мне интересно, если есть рецепт, используя itertools или другие классы в Python для:

for i1 in range(0, B1): 
    for i2 in range(f1(i1), B2): ... 
     for iN in range(fN-1(iN-1), BN) 
      dostuff(i1, i2, ... iN) 

Где есть N уровней вложенности ?
Я хочу использовать эту вспомогательную функцию, как это:
dependentProducts (Bs, фс, DoStuff),
, который возвращает список или итерацию

В идеале, реализация будет итеративной вместо рекурсивной.

+0

Забавный вопрос. У вас есть реальное применение этого? ;-) –

+0

Почему вы предпочитаете это итеративно? –

+0

@StefanPochmann Вероятно, потому что рекурсия на питоне медленная, и в некоторых случаях вы в конечном итоге нарушаете предел рекурсии ... – Bakuriu

ответ

3

Итерационное решение с использованием настройки @ LaurentLAPORTE. Поместите этот код прямо под себя, и он должен работать. Мой args представляет собой стек аргументов, который вводится в dostuff всякий раз, когда он заполнен. Фактическое решение - это средняя часть, верхняя и нижняя части - это просто тестирование.

stefan = [] 
def dostuff(*args): 
    stefan.append(list(args)) 

args = [-1] 
while args: 
    n = len(args) 
    args[-1] += 1 
    if args[-1] >= B[n-1]: 
     args.pop() 
    elif n == len(B): 
     dostuff(*args) 
    else: 
     args.append(F[n](args[-1]) - 1) 

assert expected == stefan 
+0

Благодаря вам и @Laurent LAPORTE! Поскольку вам нужна демонстрация использования, вы можете сделать следующее правильное создание скобок с простой зависимостью: https://bpaste.net/show/666281c848e9 Теперь представьте, что можно делать с разными! = D – qedpi

+1

@qedpi Если вы используете его таким образом, тогда лучше заменить 'outputs.append (g (* args))' на 'yield g (* args)' и удалить остальные элементы 'output'. –

2

Вот пример того, что вы хотите:

B = [10, 15, 20, 5] 

F = [lambda x: x, 
    lambda x: x * x, 
    lambda x: x * 2 - 5] 

def dostuff(i0, i1, i2, i3): 
    print((i0, i1, i2, i3)) 

expected = [] 
for i0 in range(0, B[0]): 
    for i1 in range(F[0](i0), B[1]): 
     for i2 in range(F[1](i1), B[2]): 
      for i3 in range(F[2](i2), B[3]): 
       expected.append([i0, i1, i2, i3]) 

Я нашел рекурсивное решение так:

def iter_rec(found, fL, bL): 
    if fL and bL: 
     ik = found[-1] if found else 0 
     fk = fL[0] 
     bk = bL[0] 
     for i in range(fk(ik), bk): 
      for item in iter_rec(found + [i], fL[1:], bL[1:]): 
       yield item 
    else: 
     yield found 

# prepend the null function to ensure F and B have the same size 
F = [lambda x: 0] + F 

current = [item for item in iter_rec([], F, B)] 

Мы имеем тот же результат.

assert expected == current 
+0

Чтобы запросить разъяснение, вы должны использовать * комментарии *. Если вам нужно было показать этот код, вы могли бы разместить его в gist (или подобной службе) и связать его с вашим комментарием. – Bakuriu

+1

Что вы думаете об этом рекурсивном решении? Для итеративного решения может потребоваться дополнительный стек ('list') ... –

+0

Спасибо, я считаю, что это работает, не могли бы вы уточнить, что требуется для итеративного решения? – qedpi

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