我正在使用该方法查看某个文本文件中的某个字符串。
re.finditer(pattern,text)
我想知道什么时候什么也没有。这意味着它在传递的文本中找不到任何内容。
我知道可调用的迭代器有next()
和__iter__
我想知道我是否可以获得大小,或者发现它是否返回不匹配我的模式的字符串。
答案 0 :(得分:17)
此解决方案使用更少的内存,因为它不会像使用list
的其他解决方案一样保存中间结果:
sum(1 for _ in re.finditer(pattern, text))
如果模式在文本中非常频繁,所有较旧的解决方案都有消耗大量内存的缺点,如模式'[a-z]'。
测试用例:
pattern = 'a'
text = 10240000 * 'a'
这个sum(1 for ...)
的解决方案大致只使用文本的内存,即len(text)
个字节。以前的list
解决方案可以使用大约58或110倍的内存。 32位分配为580 MB。 1.1 GB用于64位Python 2.7。
答案 1 :(得分:7)
编辑3: @hynekcer的答案比这要好得多。
编辑2: 如果你有一个无限的迭代器,或者耗费太多千兆字节的迭代器,那么这将无效(2010年1千兆字节仍然是大量的内存RAM /磁盘空间的/磁盘空间。
你已经看到了一个很好的答案,但这里有一个昂贵的黑客你可以使用,如果你想吃蛋糕也有它:)诀窍是我们必须克隆蛋糕,当你完成吃,我们把它放回到同一个盒子里。请记住,当迭代迭代器时,它通常变为空,或者至少丢失先前返回的值。
>>> def getIterLength(iterator):
temp = list(iterator)
result = len(temp)
iterator = iter(temp)
return result
>>>
>>> f = xrange(20)
>>> f
xrange(20)
>>>
>>> x = getIterLength(f)
>>> x
20
>>> f
xrange(20)
>>>
编辑: 这是一个更安全的版本,但使用它仍然需要一些纪律。感觉不像Pythonic。如果您发布了您尝试实施的相关代码示例,那么您将获得最佳解决方案。
>>> def getIterLenAndIter(iterator):
temp = list(iterator)
return len(temp), iter(temp)
>>> f = iter([1,2,3,7,8,9])
>>> f
<listiterator object at 0x02782890>
>>> l, f = getIterLenAndIter(f)
>>>
>>> l
6
>>> f
<listiterator object at 0x02782610>
>>>
答案 2 :(得分:5)
对不起,迭代器并不意味着知道长度,他们只知道下一步是什么让他们在通过集合时非常有效。虽然它们更快,但它们不允许索引,包括知道集合的长度。
答案 3 :(得分:1)
您可以通过执行以下操作来获取迭代器中的元素数:
len( [m for m in re.finditer(pattern, text) ] )
迭代器是迭代器,因为它们还没有生成序列。上面的代码基本上是从迭代器中提取每个项目,直到它想要停止到列表中,然后获取该数组的长度。更节省内存的东西是:
count = 0
for item in re.finditer(pattern, text):
count += 1
for循环的一个棘手方法是使用reduce来逐个有效地计算迭代器中的项。这实际上与for循环相同:
reduce( (lambda x, y : x + 1), myiterator, 0)
这基本上忽略了传递给reduce的y
并且只添加了一个。它将运行总和初始化为0
。
答案 4 :(得分:1)
虽然一些迭代器可能能够知道它们的长度(例如,它们是从字符串或列表创建的),但大部分都不能也不能。 re.iter
是一个很好的例子,在完成之前无法知道它的长度。
但是,有几种不同的方法可以改善您当前的代码:
使用re.search
查找是否有匹配项,然后使用re.finditer
进行实际处理;或
使用带有for
循环的标记值。
第二个选项类似于:
match = empty = object()
for match in re.finditer(...):
# do some stuff
if match is empty:
# there were no matches
答案 5 :(得分:0)
一个快速的解决方案是将你的迭代器变成一个列表并检查该列表的长度,但如果结果太多,那么这样做会对内存造成不利。
matches = list(re.finditer(pattern,text))
if matches:
do_something()
print("Found",len(matches),"matches")