【问题标题】:Iterating nested list inside-out从内到外迭代嵌套列表
【发布时间】:2013-02-04 07:19:06
【问题描述】:

我有以下python嵌套列表结构:

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

还是一样,只是格式化了:

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

我想知道迭代完整列表的最佳方法是什么,从最里面的嵌套列表对象 ('e') 到最外面的列表 ('a', [...], 'b')以相反的顺序。对 reversed(test) 的调用并不能解决嵌套列表的问题。它应该能够在迭代的每个深度调用回调函数。

迭代应该看起来像这样([xx] == 来自先前调用的回调的计算值):

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

希望这能解释我的问题并感谢您的帮助

【问题讨论】:

  • 扁平化列表不是一种选择吗?
  • @StoryTeller:展平会在 [b, d, e, c a] 上循环。
  • 我还认为这可能会有所帮助。问题是我必须使用回调函数计算每个嵌套列表项。展平后我不知道应该计算哪个项目...

标签: python python-3.x


【解决方案1】:

您正在寻找的是结构的后序遍历

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']

【讨论】:

  • 谢谢,这看起来比@Abhijit 的答案简单。
  • 请注意,类型检查不是pythonic - 例如,使用isinstance(x, list) 意味着这不适用于元组。还要注意这是一个递归函数,这意味着如果你有 huge 列表,你最终可能会达到最大递归深度。它也可能效率相对较低。
  • @Lattyware: isinstance(x, list) 可以很容易地更改为isinstance(x, collections.Iterable),无论如何,用户的示例只处理列表。
  • @Lattyware:如果您正在处理嵌套深度超过 1000 级的列表,您可能会遇到其他问题。 (见鬼,Python 的解析器放弃了嵌套那么深的文字)。我认为它非常有效——另一种解决方案可能会为队列使用大量额外的内存,但这种解决方案仅适用于结构的最大深度。如果你想避免递归,用显式堆栈重写是微不足道的。
  • 现在我明白了。但我认为这不能回答 OP 的问题,因为它专门 only 在每个列表的第二个元素上递归,除非那是 OP 实际上作为数据结构所具有的。我的解决方案旨在从内到外迭代完全任意的嵌套列表。
【解决方案2】:

我建议的一种可能的解决方案是

>>> 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. 深度优先遍历,将元素推入队列
  2. 循环遍历反向队列并产生元素

【讨论】:

  • 请注意,这可以在 Python >= 3.3 中简化,for e in reversed(queue): yield e 等价于 yield from reversed(queue)
猜你喜欢
  • 2011-10-14
  • 1970-01-01
  • 2013-05-11
  • 2016-12-27
  • 1970-01-01
  • 1970-01-01
  • 2014-06-08
  • 1970-01-01
  • 2014-08-19
相关资源
最近更新 更多