Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python-在迭代器中计数元素而不使用_Python - Fatal编程技术网

Python-在迭代器中计数元素而不使用

Python-在迭代器中计数元素而不使用,python,Python,给定一个迭代器it,我想要一个函数it\u count,它返回迭代器生成的元素计数,而不破坏迭代器。例如: ita = iter([1, 2, 3]) print(it_count(ita)) print(it_count(ita)) 应该打印 3 3 有人指出,对于所有迭代器来说,这可能不是一个定义良好的问题,因此我并不寻求一个完全通用的解决方案,但它应该按照给定示例的预期工作 好的,让我进一步澄清我的具体情况。给定以下代码: ita = iter([1, 2, 3]) itb, itc

给定一个迭代器
it
,我想要一个函数
it\u count
,它返回迭代器生成的元素计数,而不破坏迭代器。例如:

ita = iter([1, 2, 3])
print(it_count(ita))
print(it_count(ita))
应该打印

3
3
有人指出,对于所有迭代器来说,这可能不是一个定义良好的问题,因此我并不寻求一个完全通用的解决方案,但它应该按照给定示例的预期工作


好的,让我进一步澄清我的具体情况。给定以下代码:

ita = iter([1, 2, 3])
itb, itc = itertools.tee(ita)
print(sum(1 for _ in itb))
print(sum(1 for _ in itc))

…我们能否编写上面描述的
it\u count
函数,使其以这种方式工作?即使问题的答案是“那不可能做到”,这仍然是一个完全正确的答案。这并没有让问题变得糟糕。证明这是不可能的证据绝不是微不足道的…

不可能。直到迭代器被完全使用,它才有具体的元素计数。

获得任意迭代器长度的唯一方法是对其进行迭代,因此这里的基本问题定义不清。如果不迭代任何迭代器,就无法获得其长度

此外,迭代器本身在被迭代时可能会更改其内容,因此计数可能不是常量


但也有一些可能性可以满足您的要求,请注意,这些可能性都不是万无一失的,也不是真正有效的:

在使用python 3.4或更高版本时,您可以使用并希望迭代器支持它(请注意:迭代器不多!这只是一个提示,实际长度可能不同!):


作为替代方案:您可以使用,但在使用之前请仔细阅读该文档。它可能会解决你的问题,但不会真正解决根本问题

import itertools

def it_count(iterator):
    return sum(1 for _ in iterator)

ita = iter([1, 2, 3])
it1, it2 = itertools.tee(ita, 2)
print(it_count(it1))  # 3
print(it_count(it2))  # 3

但这比将其放入
列表并在其上使用
len
效率(内存和速度)要低。

没有通用的方法来做您想要的事情。迭代器可能没有定义好的长度(例如永远迭代的
itertools.count
)。或者,它的长度预先计算起来很昂贵,因此在到达终点之前,它不会让您知道要走多远(例如,一个文件对象,可以迭代生成行,如果不读取整个文件的内容,很难计算行数)

某些类型的迭代器可能实现返回估计长度的
\uuuu length\u hint\uuu
方法,但该长度可能不准确。并不是所有的迭代器都能实现该方法,所以您可能无法依赖它(它确实适用于列表迭代器,但不适用于其他许多迭代器)

通常,处理迭代器全部内容的最佳方法是将其转储到列表或其他容器中。完成所需的任何操作(如对其调用
len
)后,可以再次迭代列表。显然,这要求迭代器是有限的(并且它的所有内容都适合内存),但这是您必须处理的限制


如果您只需要向前看几个元素,您可能可以使用
itertools.tee
,但是如果您需要使用整个内容,这并不比将其转储到列表中要好(因为它会将返回的迭代器中的一个迭代器看到的值保留在类似于
deque
的数据结构中的另一个迭代器看到的值)。它对于查找迭代器的长度没有任何用处。

我还没有找到一个精确的解决方案(因为迭代器可能是不可变的类型),但下面是我最好的尝试。根据(itertools.tee
的最后一段),我认为第二个应该更快

选项1

def it_count(it):
   tmp_it, new_it = itertools.tee(it)
   return sum(1 for _ in tmp_it), new_it
选项2

def it_count2(it):
   lst = list(it)
   return len(lst), lst
它的功能很好,但是有一点麻烦,那就是返回配对而不是简单的计数

ita = iter([1, 2, 3])
count, ita = it_count(ita)
print(count)

Output: 3

count, ita = it_count2(ita)
print(count)

Output: 3

count, ita = it_count(ita)
print(count)

Output: 3

print(list(ita))

Output: [1, 2, 3]

到目前为止你试过什么?什么让你绊倒了?与其给出抽象的例子(这显然会导致人们告诉你,在一般情况下,这是不可能的),你能描述一下你实际上在处理什么样的迭代器,以及为什么你需要这样做吗?请不要改变问题的初衷,如果您有“跟进”问题,请发布新问题。这不是对原始问题的跟进或修改。这是对那些不理解其意图的人的澄清。迭代器的主要要点是它是惰性执行的,您可以根据需要从中获取元素,并且不一定具有定义良好的长度(因此问题不是定义不清的,您要求的功能是定义不清的)如果你真的是从列表文字构建迭代器,你只需要得到列表的
len
,那么你真正想知道的迭代器是什么?好的,那么我只需要解决方案来为确定性迭代器工作(或相关内存修改的其他技术条件等…)“你需要提前知道有多少个”子迭代器“你需要”-它的文档记录很差,但只要你保留一个副本,你就不会前进。啊,是的,完全忘记了
tee
支持
copy
。然而,我正在研究
itertools.tee
,原始迭代器仍将被使用。@抱歉,那么您需要的是用户的回答:这是不可能的。
tee
实际上没有使用
deque
-它将元素存储在一个专门的。请参见中的
teedataobject
teeobject
。您是对的,它不完全是
deque
,但是
teeobject
的链表实现与使用64个值块的双链表没有多大区别。这在某些情况下可能会起作用,但仅给出两个可能不起作用的示例:
ita=itertools.count()
l=[1,2,3];ita=地图(l.append,l)
?请注意,这些方法在技术上“消耗”了迭代器
ita = iter([1, 2, 3])
count, ita = it_count(ita)
print(count)

Output: 3

count, ita = it_count2(ita)
print(count)

Output: 3

count, ita = it_count(ita)
print(count)

Output: 3

print(list(ita))

Output: [1, 2, 3]