Ich arbeite an einem Code, bei dem ich eine verschachtelte Schleife wie folgt verwenden muss:

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])

Aber diese traditionellen verschachtelten Schleifen sehen ziemlich hässlich aus. Gibt es eine Möglichkeit, dieselbe Operation mit weniger Leitungen auszuführen?

Ich habe mir itertools.product angesehen, konnte aber nicht das bekommen, was ich will, da alle Start- / Endindizes meiner Schleifen von der vorherigen Ebene abhängen.

1
user3024444 23 Nov. 2013 im 12:27

3 Antworten

Beste Antwort

Sie können itertools.combinations verwenden und der zweite Parameter ist die Anzahl der Schleifen, die Sie ausführen möchten.

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

Ausgabe

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

Mit dem Listenverständnis wird der gesamte Code so

[list(item) for item in combinations("ABCD", 3)]
5
thefourtheye 23 Nov. 2013 im 08:48

Erstellen Sie Ihr Array direkt aus itertools.combinations, z. mit n = 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)]
>>> 

Wenn Sie nach großen Zahlen suchen, ist es möglicherweise besser, einen Generator zu schreiben, um ihn für Sie zu iterieren, oder den bereitgestellten Generator direkt zu verwenden:

arr = [i for i in combinations(range(8), 5)]
for i in arr:
   # whatever you were going to use arr for....
0
Steve Barnes 23 Nov. 2013 im 08:36

Manchmal kann diese Art von Algorithmus im Allgemeinen unter Verwendung eines rekursiven Ansatzes implementiert werden. Als Beispiel, bei dem die Iteration für das nächste Level komplexe Tests erfordert, betrachten Sie einen Acht-Königinnen -Problemlöser:

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 ...

Dieser sich wiederholende Code kann mit herausgerechnet werden

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])

Und Sie erhalten auch, dass die Anzahl der Ebenen (d. h. die Brettgröße für das Königinnenproblem) ein Parameter wird.

0
6502 23 Nov. 2013 im 08:46