2016-05-12 7 views
1
f = (3, 4, 5, {3: 4}, [16, 7, 8]) 
g = (1, 2, [3, 4, [5, 6], {7: 8}], 9, 10, {11: f}, {12: [1, 2, {3, 4}, [5, 6]]}) 

Ich versuche rekursiv über g iterieren.wie in Python 2 erschöpfend zu Iterate?

Wie jedes Element rekursiv in Python iterieren, das für jede Liste mit beliebiger Verschachtelungsebene funktioniert?

Ich habe versucht mit hasattr, __iter__, aber wird nicht mit unbekannten Verschachtelungsebene arbeiten.

f=(3,4,5,{3:4},[6,7,8]) 
g = (1, 2, [3, 4, [5, 6], {7: 8}], 9, 10, {11: (3, 4, 5, {3: 4}, [16, 7, 8])}, {12: [1, 2, set([3, 4]), [5, 6]]}) 
print g 
for each in g: 
    print each 
    try: 
     if hasattr(each,"__iter__"): 
      for ind in each: 
       print ind 
       if hasattr(ind,"__iter__"): 
        for ind1 in ind: 
         print ind1 
+0

Was macht 'f' hier? – Spacedman

+1

Sie erwähnen rekursiv, haben aber keine rekursive Funktion geschrieben - vielleicht versuchen Sie das? Beachten Sie auch, dass Strings bei Code wie diesem ein Problem darstellen können. Seien Sie vorsichtig, wenn sie sich in Ihrer Eingabe befinden. – jonrsharpe

+0

Was ist Ihre gewünschte Ausgabe? Wenn es ein Wörterbuch gibt, in dem jedes Element aus einem Schlüssel/Wert-Paar besteht, über welches man iterieren soll? Nur der Schlüssel? Nur der Wert? Beide? –

Antwort

2

Um rekursiv über etwas zu wiederholen, was Sie brauchen natürlich eine rekursive Funktion. Hier ist eine, die in list s, tuple s, set s, frozenset s und die Werte von dictionary s absteigen kann. Es gibt einen flachen Generator, über die Sie bequem in einer einzigen for Schleife durchlaufen kann:

def recursive_iterator(iterable): 
    for item in iterable: 

     # directly iterable types: 
     if type(item) in (list, tuple, set, frozenset): 
      for child_item in recursive_iterator(item): 
       yield child_item 

     # other iterable types where we do not want to iterate over the item directly: 
     elif type(item) in (dict,): 
      for child_item in recursive_iterator(item.values()): 
       yield child_item 

     # not iterable types which we want to return as they are: 
     else: 
      yield item 

Hier ist, wie Sie diese Funktion verwenden würden:

1 2 3 4 5 6 8 9 10 3 4 5 4 16 7 8 1 2 3 4 5 6 
:

f = (3, 4, 5, {3: 4}, [16, 7, 8]) 
g = (1, 2, [3, 4, [5, 6], {7: 8}], 9, 10, {11: f}, {12: [1, 2, {3, 4}, [5, 6]]}) 

for x in recursive_iterator(g): 
    print(x, end=" ") 

Der Ausgang dieses wäre

See this code running on ideone.com

+0

Sie sollten 'isinstance' wirklich verwenden und die' abc's verwenden, anstatt Typen explizit zu benennen. Zum Beispiel wird dies auf "OrderedDict" unnötig fehlschlagen. – jonrsharpe

+0

@jonrsharpe Ich dachte hauptsächlich, 'type' zu ​​verwenden, um es mit einer Liste von Typen vergleichen zu können, aber jetzt sehe ich Ihren Punkt. Wie würde ich dann am einfachsten mit vielen Gegenständen vergleichen? 'any (map (lambda t: isinstance (item, t), [Liste, Tupel, set, frozenset])) sollte auch Unterklassen der aufgelisteten Typen akzeptieren. Wie würde Ihr abc-Ansatz funktionieren? Ich habe diese noch nie benutzt. –

+0

1. 'isinstance' kann ein Tupel von Typen als zweites Argument verwenden. 2. Lesen Sie die Dokumente 'collections.abc'. – jonrsharpe