从表面上看,这似乎是重复的 find first element in a sequence that matches a predicate 但事实并非如此。
我有一个谓词函数(一个参数的函数) 处理参数并返回非None值时 处理被称为"成功"。我想使用那个功能 有效地在列表上甚至是一些可迭代但我不想 迭代列表的所有元素或迭代,但只返回 当该值不为None时,谓词函数的返回值, 然后停止在后续元素上执行谓词。
我希望有一些东西 itertools那个 会这样做,但他们似乎都很难恢复元素 传递给谓词的原始项目,而不是我想要的 返回值。
我有一个如下所示的解决方案,但代码过于繁重。我'米
想要更优雅的东西,而不需要firstof
在那里编码的效用函数。
注意:实际上是将整个文件读入一个行列表 因为我需要内存中的全部内容供其他人使用 处理
我在这里使用Python 2;我不想在此处切换到Python 3 时间,但希望避免使用已弃用或丢失的语法 在Python 3中。
import re
def match_timestamp(line):
timestamp_re = r'\d+-\d+-\d+ \d+:\d+:\d+'
m = re.search(r'^TIMESTAMP (' + timestamp_re + ')', line)
if m:
return m.group(1)
return None
def firstof(pred, items):
"""Find result from the first call to pred of items.
Do not continue to evaluate items (short-circuiting)."""
for item in items:
tmp = pred(item)
if tmp:
return tmp
return None
log_file = "/tmp/myfile"
with open(log_file, "r") as f:
lines = f.readlines()
for line in lines:
print "line", line.rstrip()
timestamp = firstof(match_timestamp, lines)
print "** FOUND TIMESTAMP **", timestamp
假设我/tmp/myfile
包含:
some number of lines here
some number of lines here
some number of lines here
TIMESTAMP 2017-05-09 21:24:52
some number of lines here
some number of lines here
some number of lines here
在它上面运行上面的程序:
line some number of lines here
line some number of lines here
line some number of lines here
line TIMESTAMP 2017-05-09 21:24:52
line some number of lines here
line some number of lines here
line some number of lines here
** FOUND TIMESTAMP ** 2017-05-09 21:24:52
答案 0 :(得分:2)
from itertools import imap, ifilter
timestamp = next(line for line in imap(match_timestamp, lines) if line)
# or
timestamp = next(ifilter(None, imap(match_timestamp, lines)))
(我相信这是在Python 2中实现它的方法,在Python 3中你只需使用map
。)
map
你的行上的函数让你得到转换值的延迟迭代器,然后懒惰地使用next
和生成器表达式ifilter
从中得到下一个真值。如果没有找到值,您可以选择是让next
引发StopIteration
错误,还是为默认返回值提供第二个参数。
答案 1 :(得分:1)
已编辑:您可以创建一个生成器并将其与next
一起使用,直到找到时间戳。
with open(log_file, "r") as f:
lines = f.readlines()
for line in lines:
print "line", line.rstrip()
timestamp = None
generator = (match_timestamp(line) for line in lines)
while timestamp is None:
timestamp = next(generator)
print "** FOUND TIMESTAMP **", timestamp