6

在容器上执行多次迭代的正确方法是什么?来自 python 文档:

迭代器 - 每次将容器对象(例如列表)传递给 iter() 函数或在 for 循环中使用它时,它都会生成一个新的迭代器。使用迭代器尝试此操作只会返回与上一次迭代过程中使用的相同的耗尽迭代器对象,使其看起来像一个空容器。

该协议的意图是一旦迭代器的 next() 方法引发 StopIteration,它将在后续调用中继续这样做。不遵守此属性的实现被视为已损坏。(此约束是在 Python 2.3 中添加的;在 Python 2.2 中,根据此规则破坏了各种迭代器。)

如果我有这个代码:

slist = [1,2,3,4]
rlist = reversed(slist)
list(rlist)
#[4,3,2,1]
tuple(rlist)
#()

迭代“rlist”两次的最简单和最正确的方法是什么?

4

4 回答 4

7
rlist = list(reversed(slist))

然后根据需要多次迭代。这个技巧更普遍适用;每当您需要多次迭代迭代器时,将其转换为列表。这是一个代码片段,我为此目的一直复制粘贴到不同的项目中:

def tosequence(it):
    """Turn iterable into a sequence, avoiding a copy if possible."""
    if not isinstance(it, collections.Sequence):
        it = list(it)
    return it

Sequence是列表、元组和许多自定义列表类对象的抽象类型。)

于 2013-04-19T15:36:43.963 回答
5

我不会将列表存储两次,如果你不能将它组合起来迭代一次,那么我会

slist = [1,2,3,4]
for element in reversed(slist):
    print element  # do first iteration stuff
for element in reversed(slist):
    print element  # do second iteration stuff

只需将 reversed() 视为在 slist 上设置反向迭代器。反面便宜。话虽这么说,如果您只需要反转它,我会反转它并像那样存储它。

于 2013-04-19T15:38:20.243 回答
4

在容器上执行多次迭代的正确方法是什么?

只需连续做两次。没问题。

迭代“rlist”两次的最简单和最正确的方法是什么?

看,不适合你的原因是它rlist 不是“容器”。

注意如何

list(slist) # another copy of the list
tuple(slist) # still works!

因此,如果您需要多次迭代,简单的解决方案是确保您拥有一个实际的项目容器:

rlist = list(reversed(slist)) # we store the result of the first iteration
# and then that result can be iterated over multiple times.

如果您确实不能存储这些物品,请尝试itertools.tee. 但请注意,如果您需要在开始下一个完整迭代之前完成一个完整的迭代,您将不会真正避免存储这些项目。在一般情况下,在这些限制下,存储确实是不可避免的。

于 2013-04-19T15:49:42.050 回答
1

为什么不简单地就地反转原始列表slist.reverse()

如果这对您不起作用,则以相反顺序迭代列表的最佳解决方案是每次需要迭代时创建一个新的反向迭代器

for _ in xrange(as_many_times_as_i_wish_to_iterate_this_list_in_reverse_order):
    for x in reversed(slist):
        do_stuff(x)
于 2013-04-19T16:01:23.270 回答