【问题标题】:Fastest way to get the first and last element of a python iterator获取python迭代器的第一个和最后一个元素的最快方法
【发布时间】:2013-12-04 22:58:39
【问题描述】:

我正在尝试对交互器的第一个和最后一个元素执行检查。它有几千个条目,所以我需要一种快速的检查方法。如果找到this post,那我就采用了这个策略。

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

有人对更快的方法有什么意见吗?非常感谢!

【问题讨论】:

  • 为什么任意迭代器都应该有最后一个元素?
  • 您的示例代码不是有效的python;您至少可以使用for item in iterable: 或类似的 Python 语法吗?
  • 请注意,else: pass完全冗余的,可以完全删除。在 Python 中,您没有必须拥有带有 if 语句的 else 子句。
  • else: pass 将退出 for 循环。我想是不需要的。谢谢。

标签: python iterator memory-efficient


【解决方案1】:

next() function获取第一个值:

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

这假设迭代是有限的。

对于空的可迭代对象,firstlast 设置为 defaultvalue。对于只有一个元素的可迭代对象,firstlast 都将引用该元素。对于任何其他有限迭代,first 将具有第一个元素,last 在最后一个元素。

【讨论】:

  • 您好 Martijn,感谢您的回答。这种技术非常 Python 并且(现在我已经解决了所有的错误)似乎工作得很好。循环遍历我的迭代器仍然需要大约 4 分钟,但它比我之前的要好。再次感谢。
  • 好的,所以我根据 Paul 的 deque 方法来计时。这种方法花了我 264 秒的时间。 deque 方法耗时 275 秒。可以说是在喧嚣之中。但是我要用这个人!谢谢。
【解决方案2】:

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

如果可用,可能值得使用__reversed__。如果您提供迭代器,并且有一种明智的方式来实现__reversed__(即不从端到端迭代),您应该这样做

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

【讨论】:

  • __reversed__ 通常只能在本身不是迭代器的对象上找到。例如。 list 提供它,但不是 iter(list)
  • 在标准库中,只有list()range()collections.deque()collections.OrderedDict()提供了__reversed__,并且没有一个本身是迭代器。这意味着您不能在他们身上调用next()
  • 我喜欢反转迭代器并避免不必要的循环的选项。不幸的是,我的迭代器没有__reversed__ 属性,无论如何我都会进入循环。感谢您的建议!
【解决方案3】:

您可以使用 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

【讨论】:

  • 所以我尝试了这种方法并为我的过程计时。耗时 275 秒。 “loop n' pass”技术耗时 264 秒。无论哪种方式,两者都具有可比性。感谢您的建议!这是一种我不知道存在的有趣技术。
【解决方案4】:

根据我的测试,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

【讨论】:

    猜你喜欢
    • 2013-02-20
    • 1970-01-01
    • 2019-10-19
    • 1970-01-01
    • 1970-01-01
    • 2013-12-01
    • 1970-01-01
    • 2011-01-09
    • 2014-12-19
    相关资源
    最近更新 更多