获取Python迭代器的第一个和最后一个元素的最快方法

9

我想对一个迭代器的第一个和最后一个元素进行检查。由于它有数千条条目,因此我需要一种快速的检查方法。我找到了这篇文章,并从中了解到了以下策略。

first = True
for value in iterator:
   if first:
      do_stuff_to_first_iter
      first = False
   else:
      pass
do_stuff_to_last_iter

有没有人对更快地完成这个任务有什么看法?非常感谢!


2
任意迭代器为什么需要有最后一个元素? - Hyperboreus
2
你的示例代码不是有效的Python代码;你能否至少使用for item in iterable:或类似的Python语法? - Martijn Pieters
1
请注意,else: pass是完全多余的,可以完全省略。在Python中,您不必使用if语句的else子句。 - Martijn Pieters
else: pass 是为了退出 for 循环。我想这不是必要的。谢谢。 - Rich
4个回答

30

使用 next() 函数获取第一个值:

first = last = next(iterable, defaultvalue)
for last in iterable:
    pass

这假设可迭代对象是有限的。
对于一个空的迭代对象,firstlast 都设置为 defaultvalue。对于只有一个元素的迭代对象,firstlast 都将指向该元素。对于任何其他有限的迭代对象,first 将会是第一个元素,last 是最后一个元素。

你好Martijn,感谢你的回答。这种技术非常符合Python的风格,并且(现在我已经解决了所有的错误)似乎运行得非常好。虽然循环迭代器仍需要大约4分钟,但比之前的方法要好得多。再次感谢。 - Rich
好的,所以我对比了一下Paul的deque方法。这个方法花费了264秒。而deque方法则花费了275秒。可以说差别不大。但是我会使用这个方法!谢谢。 - Rich

3

根据我对链接问题的回答:

如果可用,建议使用__reversed__。如果您正在提供迭代器,并且有一种合理的方法来实现__reversed__(即不需要从头到尾进行迭代),则应该这样做。

first = last = next(my_iter)
if hasattr(my_iter,'__reversed__'):
    last = next(reversed(my_iter))
else:
    for last in my_iter:
        pass

1
“__reversed__”通常只在不是迭代器本身的对象中找到。例如,list提供它,但不提供iter(list) - Martijn Pieters
1
在标准库中,只有 list()range()collections.deque()collections.OrderedDict() 提供了 __reversed__,而且它们本身都不是迭代器。这意味着你不能对它们调用 next() - Martijn Pieters
我喜欢反转迭代器并避免不必要的循环选项。不幸的是,我的迭代器没有__reversed__属性,所以我还是得进入循环。感谢您的建议! - Rich

1
根据我的测试,islicefor: passdeque 快3倍。不过这需要您提前知道有多少项。
last = next(islice(iterable, length - 1, length))

如果你不知道完整长度,但是知道它必须至少n,你仍然可以通过跳过到n来快速完成:

rest = islice(iterable, n, None)
last = next(rest)
for last in rest:
    pass

1
你可以使用 maxlen 为 1 的 deque 快速获取有限迭代器的最后一个元素:
>>> from collections import deque
>>> last_getter = deque(maxlen=1)
>>> seq = range(10000)
>>> iseq = iter(seq)
>>>
>>> first = last = next(iseq, None)
>>> last_getter.extend(iseq)
>>> if last_getter: last = last_getter[0]
...
>>> print (first, last)
0 9999

1
所以我尝试了这种方法并为我的进程计时。花费了275秒。 "循环传递"技术花费了264秒。无论哪种方式,两者都是可比的。谢谢你的建议!这是一种我不知道存在的有趣技术。 - Rich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接