在列表上迭代两次的正确方法?

时间:2013-04-19 15:35:06

标签: python

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

  

迭代器 - 容器对象(例如列表)产生一个全新的   迭代器每次将它传递给iter()函数或在a中使用它   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 个答案:

答案 0 :(得分: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是列表,元组和许多自定义列表类对象的抽象类型。)

答案 1 :(得分: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

只需将reverse()视为在slist上设置反向迭代器。逆转是便宜的。话虽这么说,如果你只需要颠倒它,我会反转它,只是把它存储起来。

答案 2 :(得分:3)

  

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

连续两次做。没问题。

  

两次迭代'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。但请注意,如果您需要在开始下一个完整迭代之前完成一次完整迭代,则不会真正避免存储这些项目。在一般情况下,在这些限制下存储是不可避免的。

答案 3 :(得分: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)