首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >查找Python中序列上谓词的第一个非无返回值。

查找Python中序列上谓词的第一个非无返回值。
EN

Stack Overflow用户
提问于 2017-05-11 04:20:29
回答 2查看 651关注 0票数 0

表面上看,这似乎是查找与谓词匹配的序列中的第一个元素的复制,但事实并非如此。

我有一个谓词函数(一个参数的函数),它对参数进行一些处理,并在处理被称为“成功”时返回一个非无值。我想有效地在列表上使用这个函数,甚至是一些可迭代的函数,但是我不想对列表中的所有元素进行迭代,而是在谓词函数的返回值不是None时返回它,然后停止对后续元素执行谓词。

我本来希望迭代工具中有一些东西可以做到这一点,但它们似乎都是硬连接起来的,可以返回传递给谓词的原始项的元素,相反,我需要返回的值。

下面显示了一个解决方案,但是代码太重了。我想要一些更优雅的东西,这不需要在那里编码firstof实用程序函数。

注意:在这里,将整个文件读入行列表实际上是必要的,因为我需要内存中的全部内容来进行其他处理。

我在这里使用Python 2;此时我不想切换到Python 3,但希望避免使用Python 3中不推荐或缺少的语法。

代码语言:javascript
复制
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包含:

代码语言:javascript
复制
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

在其上运行上述程序:

代码语言:javascript
复制
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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-11 05:00:38

代码语言:javascript
复制
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)))

(我相信这就是在Python2中这样做的方法,在Python3中,您只需使用map。)

map函数位于您的行上,因此您可以获得转换值的懒惰迭代器,然后惰性地使用next和生成器表达式或ifilter从它获得下一个真实值。如果没有找到值,您可以选择是否让next引发StopIteration错误,或者为默认返回值提供第二个参数。

票数 2
EN

Stack Overflow用户

发布于 2017-05-11 04:29:10

编辑:您可以创建一个生成器并将其与next一起使用,直到找到时间戳为止。

代码语言:javascript
复制
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
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43906476

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档