2013-02-19 3 views
2

У меня есть следующий питона вложенного списка структуру:Итерация вложенный список наизнанку

test = ['a', ['c', ['e'], 'd'], 'b'] 

или же, просто отформатированный:

test = [ 
    'a', 
     [ 
      'c', 
       [ 
        'e' 
       ], 
      'd' 
     ], 
    'b' 
] 

Я задавался вопросом, что лучше всего было бы итерацию над полным списком, начиная с самого внутреннего вложенного объекта списка ('e') в самый внешний список ('a', [...], 'b') в обратном порядке. Вызов для вспять (тест) просто не делает трюк с вложенными списками. И он должен быть способен вызвать функцию обратного вызова на каждой глубине итерации.

Итерация должна выглядеть следующим образом ([ое] == вычисленное значение от ранее вызываемой функции обратного вызова):

1st e --> callback(e) 
2nd c [e] d --> callback(c [e] d) 
3rd a [c e d] b --> callback(a [c e d] b) 

Надеется, что это объясняет мою проблему & спасибо за вашу помощь

+0

Сглаживает ли список без опции? – StoryTeller

+0

@StoryTeller: вместо этого сглаживание будет выполняться над '[b, d, e, c a ]'. –

+0

Я также сказал, что это может помочь. Проблема в том, что я должен рассчитать каждый вложенный элемент списка с функцией обратного вызова. После сплющивания я понятия не имею, какой предмет должен быть рассчитан ... – hetsch

ответ

6

Что вы ищете является postorder обходом структуры:

def traverse(l): 
    for x in l: 
     if isinstance(x, list): 
      traverse(x) 
    callback(l) 

Если callback определяется как print, мы получаем

['e'] 
['c', ['e'], 'd'] 
['a', ['c', ['e'], 'd'], 'b'] 
+2

Спасибо, это выглядит проще, чем @Abhijit ответ. – hetsch

+0

Обратите внимание, что проверка типов не является pythonic - и использование 'isinstance (x, list)' означает, что это не будет работать, например, с кортежами. Также обратите внимание, что это рекурсивная функция, означающая, что если у вас есть * огромные * списки, вы можете достичь максимальной глубины рекурсии. Это также, вероятно, будет относительно неэффективным. –

+2

@Lattyware: 'isinstance (x, list)' можно легко изменить на 'isinstance (x, collections.Iterable)', в любом случае пример пользователя обрабатывает только списки. – Abhijit

6

Одним из возможных решений I предложит это

>>> def foo(test): 
    queue = [] 
    try: 
     while True: 
      queue.append(test) 
      test = test[1] 
    except IndexError: 
     for e in reversed(queue): 
      yield e 


>>> data = foo(test) 
>>> next(data) 
['e'] 
>>> next(data) 
['c', ['e'], 'd'] 
>>> next(data) 
['a', ['c', ['e'], 'd'], 'b'] 
>>> next(data) 

Traceback (most recent call last): 
    File "<pyshell#753>", line 1, in <module> 
    next(data) 
StopIteration 
>>> 

Как это работает

  1. Traverse глубина первый и раздвигать элементы в очереди
  2. Loop через обращенную очередь и дают элементы
+0

Спасибо, похоже, хорошее решение !!! Придется проверить это ... – hetsch

+0

Идеальный ..., спасибо! – hetsch

+0

Обратите внимание, что это можно упростить в Python> = 3.3, 'для e в обратном порядке (очередь): yield e' эквивалентно' yield from reverse (queue) '. –