2013-11-23 2 views
1

Я работаю на коде, где мне нужно использовать вложенный цикл следующим образом:Каков наилучший способ написать несколько вложенных для петель в Python

for r in range(m): 
    for s in range(r+1, m): 
     for t in range(s+1, m): 
     for u in range(t+1, m): 
      for v in range(u+1, m): 
        arr.append([r,s,t,u,v]) 

Но это традиционные вложенные циклы выглядят довольно некрасиво. Есть ли способ выполнить ту же операцию с меньшим количеством строк?

Я посмотрел на itertools.product, но я не смог получить то, что хочу, так как все начальные/конечные индексы моих циклов зависят от предыдущего уровня.

ответ

5

Вы можете использовать itertools.combinations, а второй параметр - количество циклов, которые вы хотели выполнить.

from itertools import combinations 
for item in combinations("ABCD", 3): 
    print item 

Выход

('A', 'B', 'C') 
('A', 'B', 'D') 
('A', 'C', 'D') 
('B', 'C', 'D') 

Итак, с пониманием списка, весь код становится как этот

[list(item) for item in combinations("ABCD", 3)] 
+0

Да, я плохо прочитал название и увидел ваш ответ, а затем увидел его код –

+0

@JoelGreen Thats okay :) – thefourtheye

+0

это потрясающе, спасибо большое! – user3024444

0

Создать свой массив непосредственно из itertools.combinations, например используя п = 8:

>>> from itertools import combinations 
>>> arr = [i for i in combinations(range(8), 5)] 
>>> arr 
[(0, 1, 2, 3, 4), (0, 1, 2, 3, 5), (0, 1, 2, 3, 6), (0, 1, 2, 3, 7), (0, 1, 2, 4, 5), (0, 1, 2, 4, 6), (0, 1, 2, 4, 7), (0, 1, 2, 5, 6), (0, 1, 2, 5, 7), (0, 1, 2, 6, 7), (0, 1, 3, 4, 5), (0, 1, 3, 4, 6), (0, 1, 3, 4, 7), (0, 1, 3, 5, 6), (0, 1, 3, 5, 7), (0, 1, 3, 6, 7), (0, 1, 4, 5, 6), (0, 1, 4, 5, 7), (0, 1, 4, 6, 7), (0, 1, 5, 6, 7), (0, 2, 3, 4, 5), (0, 2, 3, 4, 6), (0, 2, 3, 4, 7), (0, 2, 3, 5, 6), (0, 2, 3, 5, 7), (0, 2, 3, 6, 7), (0, 2, 4, 5, 6), (0, 2, 4, 5, 7), (0, 2, 4, 6, 7), (0, 2, 5, 6, 7), (0, 3, 4, 5, 6), (0, 3, 4, 5, 7), (0, 3, 4, 6, 7), (0, 3, 5, 6, 7), (0, 4, 5, 6, 7), (1, 2, 3, 4, 5), (1, 2, 3, 4, 6), (1, 2, 3, 4, 7), (1, 2, 3, 5, 6), (1, 2, 3, 5, 7), (1, 2, 3, 6, 7), (1, 2, 4, 5, 6), (1, 2, 4, 5, 7), (1, 2, 4, 6, 7), (1, 2, 5, 6, 7), (1, 3, 4, 5, 6), (1, 3, 4, 5, 7), (1, 3, 4, 6, 7), (1, 3, 5, 6, 7), (1, 4, 5, 6, 7), (2, 3, 4, 5, 6), (2, 3, 4, 5, 7), (2, 3, 4, 6, 7), (2, 3, 5, 6, 7), (2, 4, 5, 6, 7), (3, 4, 5, 6, 7)] 
>>> 

Если вы ищете большие цифры, которые вы могли бы быть лучше писать генератор для итерации это для вас или с помощью прилагаемого генератора непосредственно:

arr = [i for i in combinations(range(8), 5)] 
for i in arr: 
    # whatever you were going to use arr for.... 
0

Иногда этот вид алгоритм в целом может быть реализован с использованием рекурсивного подхода. В качестве примера, где итерации для следующего уровня требует комплексного тестирования рассмотреть eight-queens проблемы решатель в:

for col0 in range(8): 
    for col1 in range(8): 
     if col1 != col0 and not same_diag(0, col0, 1, col1): 
      for col2 in range(8): 
       if (col2 != col1 and 
        col2 != col0 and 
        not same_diag(0, col0, 2, col0) and 
        not same_diag(1, col1, 2, col2)): 
        for col3 in range(8): 
         ... same pattern up to col7 ... 

этот повторяющийся код может быть разложен с

def find_solution(i, free_cols, placed_queens): 
    if i == 8: 
     print_solution(placed_queens) 
    else: 
     for col in free_cols: 
      if not any(same_diag(i, col, j, q) 
         for j, q in enumerate(placed_queens)): 
       find_solution(i+1, 
           free_cols - set([col]), 
           placed_queens + [col]) 

и вы также получите, что количество уровней (т.е. размер платы для проблемы ферзей) становится параметром.

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