2014-01-23 16 views
16

Ich habe zwei Wörterbücher. Ich bin über das eine iterieren. Ich möchte das nächste Element jedes Mal auswählen, wenn es innerhalb der inneren Schleife statt von Anfang an iteriert.Python über Wörterbücher iterieren

dict1={'a':1 , 'b':2 , 'c':3} 
dict2={'x':10, 'y':20, 'z':30} 

for key,value in dict1: 
    #do something 
    for k,v in dict2: 
      #do something 

Wenn ‚a‘ key =, iteriert die innere Schleife über und führt eine Aktion entsprechend den Code in diesem loop.Suppose dass es Aktion, die es war ‚X‘ ausgewählt in dict2. Jetzt, wenn ich mit key = 'b' iterieren muss, möchte ich die Iteration für die innere Schleife von 'y' beginnen, weil 'x' bereits ausgewählt wurde.

+0

Also im Grunde Sie durch beide wollen Schritt zur gleichen Zeit ? – StephenTG

+0

ja. @StephenTG – Mark

+2

Die Schlüssel in einem Diktat sind ungeordnet. Jede Taste in 'dict1' kann mit einer beliebigen Taste in' dict2' gepaart werden. – unutbu

Antwort

13

Erstens, for key,value in dict1 nicht tun, was Sie wollen-es iteriert nur über die Tasten. Wenn Sie das Schlüssel/Wert-Paar durchlaufen möchten, benötigen Sie for key, value in dict1.items().

In der Zwischenzeit klingt es nach dem, was Sie fragen, ist Sperre-Schritt-Iteration, nicht verschachtelte Iteration? Wenn ja, möchten Sie die zip Funktion:

for (k1, v1), (k2, v2) in zip(dict1.items(), dict2.items()): 
    # do something 

Aber beachten Sie, dass die Reihenfolge dies tatsächlich gibt Ihnen beliebig sein wird, da die Reihenfolge der dicts von Natur aus willkürlich ist. Also, wenn Sie glücklich sind mit ('a', 'x'), dann ('b', 'y'), etc., und auch glücklich mit ('a', 'y'), dann ('b', 'x'), dann zip ist was Sie wollen. Wenn nicht, ist es nicht.

(Wenn Sie erwartet haben, dass Ihre dict s eine inhärente Reihenfolge hat, wie Reihenfolge der Einfügung oder sortierte Reihenfolge oder irgendetwas anderes, müssen Sie eine andere Klasse verwenden. Zum Beispiel funktioniert collections.OrderedDict wie ein Wörterbuch, aber hält den Anzeigenauftrag)


Wenn Sie etwas komplizierter wollen, wo Sie die Iteration über dict2 programmatisch in einer Art und Weise bewegen Sie sich nicht in einem Einzeiler zum Ausdruck bringen können, immer die iteration protocol manuell verwenden kann.:

iter2 = iter(dict2.items()) 
for k1, v1 in dict1.items(): 
    k2, v2 = next(iter2) 
    # do something 
    # maybe do another k2, v2 = next(iter2) 
    # maybe restart iter2 = iter(dict2.items()) 
    # and so on 

Wie die Dokumentation erklärt, wenn next(iter2) zum Ende kommt, erhöht es StopIteration. Was, wenn du das nicht willst? Vielleicht möchten Sie, wie Sie in einem Kommentar vorgeschlagen haben, von vorn beginnen? Sie können das lösen, indem Sie StopIteration abfangen, oder indem Sie das Zwei-Argument-Formular von next verwenden und nach einem Sentinel suchen. Zum Beispiel:

try: 
    k2, v2 = next(iter2) 
except StopIteration: 
    iter2 = iter(dict2.items()) 
    k2, v2 = next(iter2) 

Oder Sie können sogar eine Kreis Iteration Wrapper schreiben:

def circular_iterate(iterable_factory): 
    while True: 
     yield from iterable_factory(): 

In Python 3.2 oder früher, haben Sie die yield from mit einer inneren Schleife ersetzen:

def circular_iterate(iterable_factory): 
    while True: 
     for value in iterable_factory(): 
      yield value 

Und jetzt:

iter2 = circular_iterate(dict2.items) # note, not dict2.items() 

Wenn Sie versuchen, mehr als nur eine "aktuelle Position" zu verfolgen, benötigen Sie wahrscheinlich eine zusätzliche Datenstruktur.Zum Beispiel, wenn Sie alle Schlüssel überspringen wollen bisher gesehen, verwenden Sie ein set des Schlüssels bisher gesehen oder ein set des Schlüssels nicht gesehen:

seen_items_2 = set() 
for k1, v1 in dict1.items(): 
    for k2, v2 in dict2.items(): 
     if k2 in seen_items_2: 
      continue 
     seen_items_2.add(k2) 
     # do something 
+0

Ich habe bereits das Wörterbuch OrderedDict.Just das äußere – Mark

+0

Ich denke, das wird das Problem zu lösen.Ich frage mich, ob nächste (iter2) gehen bak, um zu starten, wenn es das Ende des Wörterbuchs – Mark

+0

@Nikhil: No, ' next (iter2) 'wird eine' StopIteration' auslösen, wenn sie das Ende erreicht; Ich erkläre Ihnen, wie Sie tun können, was Sie wollen, und fügen Sie Links hinzu, damit Sie das selbst herausfinden können (tut mir leid, dass ich sie vergessen habe); Gib mir eine Sekunde, um die Antwort zu bearbeiten. – abarnert