在Python

时间:2017-05-11 04:20:29

标签: python python-2.7 itertools

从表面上看,这似乎是重复的 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

2 个答案:

答案 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