2016-05-12 2 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]]}) 

Я пытаюсь повторить рекурсивно над g.Как Итерировать в исчерпывающе в python 2?

Как перебирать каждый элемент рекурсивно в python, который работает для любого списка с любым уровнем вложенности?

Я пробовал с hasattr, __iter__, но не будет работать с неизвестным уровнем гнездования.

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

Что здесь 'f'? – Spacedman

+1

Вы упоминаете рекурсивно, но на самом деле не написали рекурсивную функцию - возможно, попробуйте? Также обратите внимание, что строки могут быть проблемой с кодом, подобным этому, будьте осторожны, если они могут быть на вашем входе. – jonrsharpe

+0

Каков ваш желаемый результат? Если есть словарь, где каждый элемент состоит из пары ключ/значение, какой из них следует перебирать? Только ключ? Только значение? И то и другое? –

ответ

2

Чтобы рекурсивно перебрать что-то, вам, конечно, нужна рекурсивная функция. Вот один из них, который может опуститься до list s, tuple s, set s, frozenset s и значения of dictionary s. Она возвращает плоский генератор, по которому вы можете легко перебирать в одном for цикла:

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 

Вот как вы будете использовать эту функцию:

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=" ") 

Выходной сигнал будет следующим образом:

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

See this code running on ideone.com

+0

Вы действительно должны использовать 'isinstance', и подумайте над использованием типов' abc ', а не явно имен. Например, это будет бесполезно на 'OrderedDict'. – jonrsharpe

+0

@jonrsharpe Я в основном думал использовать «тип», чтобы иметь возможность сравнивать его со списком типов, но теперь я вижу вашу точку. Как бы я сравнил с большинством пунктов самый простой способ? 'if any (map (lambda t: isinstance (item, t), [list, tuple, set, frozenset]))' также должен принимать подклассы перечисленных типов. Как будет работать ваш подход abc? Я их еще не использовал. –

+0

1. 'isinstance' может принимать кортеж типов как второй аргумент. 2. Прочитайте документы 'collections.abc'. – jonrsharpe

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