variable anzahl an verschachtelten for-schleifen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
netzmensch
User
Beiträge: 11
Registriert: Montag 5. Februar 2007, 12:36

hi,

ich möchte eine variable zahl an for-schleifen ineinander verschachteln, komme aber einfach nicht auf die passende idee das zu realisieren

das meine ich:

Code: Alles auswählen


test = ["a","b","c"]
test2 = ["1","2","3"]
test3 = ["x","y","z"]

for a in test:
   for b in test2:
      for c in test3:
          .....
nun will ich es möglich machen, das ich z.b. (durch auswahl des users) nur die ersten beiden for schleifen nutze, oder halt alle drei, oder mehr...

der netzmensch
[size=75]Edit (Leonidas): Bild in der Signatur nach mehrfacher Warnung gelöscht.[/size]
joost
gelöscht
Beiträge: 134
Registriert: Sonntag 29. April 2007, 13:28

Verstehe ich Dein Problem mit folgendem Code richtig ?

Code: Alles auswählen

test = ["a","b","c"]
test2 = ["1","2","3"]
test3 = ["x","y","z"]

for a in test:
    if user=='aNotAllowed': break    
    for b in test2:
        if user=='bNotAllowed': break
        for c in test3:
usw.

Wenn die Erlaubnis 'springen' können soll, dann vielleicht so:

Code: Alles auswählen

test = ["a","b","c"]
test2 = ["1","2","3"]
test3 = ["x","y","z"]

for a in test:
    for b in test2:
        if user=='bMustBe2' and b!=2: continue 
        for c in test3:
Noch weitergehend könnte man Listen für User aufbauen, mit je einem Eintrag pro 'for'.
[color=green][size=75]Never use idle.pyw, if you need sys.stdin[/size][/color]
Benutzeravatar
sunmountain
User
Beiträge: 89
Registriert: Montag 13. März 2006, 17:18

Wenn Du Deine Listen in einem dict organisieren würdest,
könntest Du geziehlt welche auswählen.
Das dynamische Schachteln halte ich im Moment nur für möglich,
wenn man sich das dazugehörige Codestück dynamisch zusammenbaut
und anschliessend mit eval/exec ausführt.

Code: Alles auswählen


lists = {'test1':[1,2,3,4],'test2':[1,2,3,4],'test3':[1,2,3,4]} # die Listen
order = ('test3','test1','test2') # Die Schachtelung
forbidden = () # Alle sollen laufen
snippet = ''

def ident(n):
    return '    '*n

for n,o in enumerate([o for o in order if o not in forbidden]):
    snippet += ident(n) + '%s = %s' % (o,repr(lists[o])) + '\n'
    snippet += ident(n) + 'for a%i in %s:'  % (n,o) + '\n'
    snippet += ident(n+1) + 'print "%s",a%i' % (o,n) + '\n'

print snippet
exec(snippet)

Ergebnis:

Code: Alles auswählen

test3 = [1, 2, 3, 4]
for a0 in test3:
    print "test3",a0
    test1 = [1, 2, 3, 4]
    for a1 in test1:
        print "test1",a1
        test2 = [1, 2, 3, 4]
        for a2 in test2:
            print "test2",a2

test3 1
test1 1
test2 1
test2 2
test2 3
test2 4
test1 2
test2 1
test2 2
test2 3
test2 4
test1 3
test2 1
test2 2
test2 3
test2 4
test1 4
test2 1
test2 2
test2 3
test2 4
test3 2
test1 1
test2 1
test2 2
test2 3
test2 4
test1 2
test2 1
test2 2
test2 3
test2 4
test1 3
test2 1
test2 2
test2 3
test2 4
test1 4
test2 1
test2 2
test2 3
test2 4
test3 3
test1 1
test2 1
test2 2
test2 3
test2 4
test1 2
test2 1
test2 2
test2 3
test2 4
test1 3
test2 1
test2 2
test2 3
test2 4
test1 4
test2 1
test2 2
test2 3
test2 4
test3 4
test1 1
test2 1
test2 2
test2 3
test2 4
test1 2
test2 1
test2 2
test2 3
test2 4
test1 3
test2 1
test2 2
test2 3
test2 4
test1 4
test2 1
test2 2
test2 3
test2 4
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Rekursion ist das Stichwort.
joost
gelöscht
Beiträge: 134
Registriert: Sonntag 29. April 2007, 13:28

Ach, ich merke gerade: In meinem zweiten Beispiel sollte es auch besser 'break' statt 'continue' heißen.

Und eine Rekursion kann man machen, zusammen mit einem dict wie

PermissionDict['aNotAllowed'] = (1,0,0,0,0 ...)
PermissionDict['cNotAllowed'] = (1,1,0,0,0, ...)
PermissionDict['aAndcAllowed] = (1,0,1,0,0,..)

- man wird aber wohl doch immer eine feste Tiefe der for-Schachtelung haben (vielleicht auch wegen der - wahrscheinlich ja konstanten - Start-Listen). Dann wäre Rekursion mir persönlich zu teuer.
[color=green][size=75]Never use idle.pyw, if you need sys.stdin[/size][/color]
netzmensch
User
Beiträge: 11
Registriert: Montag 5. Februar 2007, 12:36

also der tip von sunmountain trifft es am besten...hab mich schon ne weile gefragt wozu das exec eigentlich gut ist...nun weiß ich es. danke!
[size=75]Edit (Leonidas): Bild in der Signatur nach mehrfacher Warnung gelöscht.[/size]
BlackJack

Stilistisch ist der Tip nicht so gut. Rekursion wäre die sauberere Lösung. Wenn man in einer dynamischen Sprache auf Code-Generierung zurück greift, macht man im allgemeinen etwas falsch. Und in diesem Falle wäre das nicht einmal in einer statischen Sprache nötig.
netzmensch
User
Beiträge: 11
Registriert: Montag 5. Februar 2007, 12:36

rekursiv habe ich mir auch schon überlegt, aber ich komme nicht drauf wie ich das realisieren kann...

meine idee dazu war folgendes:

Code: Alles auswählen

def schleife(anzahl_schleifen, array):
     for i in anzahl_schleifen:
        for b in array:
            schleife(?hier weiß ich nicht was rein soll?, array)
            

test1 = ["a","b","c"]

schleife(3,test1)

problem dabei ist nun, das ich nicht drauf komme die anzahl bei der rekursion richtig zu wählen, und ausserdem weiß ich nicht wie ich mir nacheinander alle state's der schleifen pro durchlauf returnen lassen kann.
ich möchte quasi alle möglichen kombinationen der schleifen zurückgegeben haben.
[size=75]Edit (Leonidas): Bild in der Signatur nach mehrfacher Warnung gelöscht.[/size]
BlackJack

Hier ist eine iterative Lösung bei der sowohl die Anzahl der Listen als auch deren Längen flexibel sind:

Code: Alles auswählen

from itertools import imap
from operator import mul


def combinations(iterable):
    sequences = list(reversed(iterable))
    max_value = reduce(mul, imap(len, sequences))
    for value in xrange(max_value):
        result = list()
        for sequence in sequences:
            value, index = divmod(value, len(sequence))
            result.append(sequence[index])
        result.reverse()
        yield result


def main():
    test1 = ['a','b','c']
    test2 = ['1','2','3']
    test3 = ['x','y','z']
    
    for a in test1:
        for b in test2:
            for c in test3:
                print [a, b, c]
    
    for combination in combinations((test1, test2, test3)):
        print combination
Die beiden Schleifen geben das gleiche aus.

Edit: In `combinations()` die `lengths`-Liste entfernt und damit die innere Schleife etwas lesbarer gemacht.
Zuletzt geändert von BlackJack am Montag 7. Mai 2007, 17:20, insgesamt 1-mal geändert.
joost
gelöscht
Beiträge: 134
Registriert: Sonntag 29. April 2007, 13:28

Hübsch ! :)
[color=green][size=75]Never use idle.pyw, if you need sys.stdin[/size][/color]
Antworten