我不知道是否有一个原因,有一个在Python的内置功能,有点类似于first(iterable)any(iterable)没有all(iterable)(它可能是一个STDLIB模块中藏的地方,但我没有看到它在itertools) 。 first将执行,使得能够避免不必要的(和潜在的无限数目)的操作的短路发生器评价;即。

def identity(item):
    return item

def first(iterable, predicate=identity):
    for item in iterable:
        if predicate(item):
            return item
    raise ValueError('No satisfactory value found')

这样你就可以表达的东西,如:

denominators = (2, 3, 4, 5)
lcd = first(i for i in itertools.count(1)
    if all(i % denominators == 0 for denominator in denominators))

显然,你不能这样做在这种情况下list(generator)[0],因为发电机不会终止。

或者,如果你有一大堆正则表达式的匹配对(有用的,当它们都具有相同的groupdict接口):

match = first(regex.match(big_text) for regex in regexes)

您通过避免在正匹配list(generator)[0]和短路节省大量不必要的处理。

有帮助吗?

解决方案

如果你有一个迭代器,你可以调用它的next方法。是这样的:

In [3]: (5*x for x in xrange(2,4)).next()
Out[3]: 10

其他提示

我问了一个类似的问题最近(它得到了标记为重复现在这个问题)。我担心的也是,我会喜欢用内建的只有的解决找到一个发电机的第一个真正的价值的问题。然后自己的解决方案是这样的:

x = next((v for v in (f(x) for x in a) if v), False)

有关找到第一个正则表达式的匹配的示例中,这是这样的(不是第一匹配图案!):

patterns = [ r'\d+', r'\s+', r'\w+', r'.*' ]
text = 'abc'
firstMatch = next(
  (match for match in
    (re.match(pattern, text) for pattern in patterns)
   if match),
  False)

它不计算谓词两次(因为你必须做,如果返回刚才的模式),它并没有在内涵使用像当地人黑客。

但是它有两个发电机嵌套其中,所述逻辑将决定只使用一个。因此,一个更好的解决办法将是不错的。

有在itertools一个“切片”的迭代器。它模拟的是我们熟悉的Python切片操作。你正在寻找的是类似这样的:

myList = [0,1,2,3,4,5]
firstValue = myList[:1]

使用itertools用于迭代器的等效的:

from itertools import islice
def MyGenFunc():
    for i in range(5):
        yield i

mygen = MyGenFunc()
firstValue = islice(mygen, 0, 1)
print firstValue 

有在你的问题有些含糊不清。您的第一并正则表达式示例的定义意味着存在一个布尔测试。但分母例如明确有一个if子句;因此它只的每个整数恰好是真巧合。

它看起来像未来的结合,itertools.ifilter会给你想要的东西。

match = next(itertools.ifilter(None, (regex.match(big_text) for regex in regexes)))

的Haskell利用了您刚刚描述的内容,作为函数take(或作为部分功能take 1,在技术上)。 Python的食谱具有书面发电机封装的执行相同功能如taketakeWhiledrop在Haskell。

但是,为什么这不是一个内置的,你猜我的一样好。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top