cdl*_*ary 66 python iterator generator
我不知道是否有一个原因,有没有first(iterable)在Python内置的功能,有点类似于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')
Run Code Online (Sandbox Code Playgroud)
这样你可以表达如下内容:
denominators = (2, 3, 4, 5)
lcd = first(i for i in itertools.count(1)
if all(i % denominators == 0 for denominator in denominators))
Run Code Online (Sandbox Code Playgroud)
很明显,list(generator)[0]在这种情况下你不能这样做,因为发生器不会终止.
或者,如果你有一堆正则表达式匹配(当它们都具有相同的groupdict接口时很有用):
match = first(regex.match(big_text) for regex in regexes)
Run Code Online (Sandbox Code Playgroud)
通过避免list(generator)[0]和短路匹配来节省大量不必要的处理.
lio*_*ori 47
如果你有一个迭代器,你可以调用它的next方法.就像是:
In [3]: (5*x for x in xrange(2,4)).next()
Out[3]: 10
Run Code Online (Sandbox Code Playgroud)
Fli*_*imm 13
>>> from first import first
>>> first([0, None, False, [], (), 42])
42
Run Code Online (Sandbox Code Playgroud)
以下是用于返回第一个奇数的方法,例如:
>> first([2, 14, 7, 41, 53], key=lambda x: x % 2 == 1)
7
Run Code Online (Sandbox Code Playgroud)
如果您只想从迭代器返回第一个元素而不管它是否为真,请执行以下操作:
>>> first([0, None, False, [], (), 42], key=lambda x: True)
0
Run Code Online (Sandbox Code Playgroud)
它是一个非常小的包:它只包含这个函数,它没有依赖关系,它适用于Python 2和3.它是一个文件,所以你甚至不必安装它来使用它.
事实上,这里几乎是整个源代码(来自版本2.0.1,由Hynek Schlawack,在MIT许可下发布):
def first(iterable, default=None, key=None):
if key is None:
for el in iterable:
if el:
return el
else:
for el in iterable:
if key(el):
return el
return default
Run Code Online (Sandbox Code Playgroud)
Alf*_*lfe 10
我最近问了一个类似的问题(现在它被标记为这个问题的副本).我担心的也是,我会喜欢使用内置插件只解决发现发电机的第一个真正的价值的问题.我自己的解决方案是这样的:
x = next((v for v in (f(x) for x in a) if v), False)
Run Code Online (Sandbox Code Playgroud)
对于查找第一个正则表达式匹配(不是第一个匹配模式!)的示例,这将如下所示:
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)
Run Code Online (Sandbox Code Playgroud)
它不会对谓词进行两次评估(如果只返回模式就必须这样做)并且它不会在理解中使用像本地人这样的黑客.
但它有两个嵌套的生成器,逻辑只能指定使用一个.所以更好的解决方案会很好.
你的问题有些含糊不清.你对first和regex例子的定义意味着有一个布尔测试.但是分母示例明确地有一个if子句; 所以每个整数恰好都是真的只是巧合.
看起来next和itertools.ifilter的组合会给你你想要的东西.
match = next(itertools.ifilter(None, (regex.match(big_text) for regex in regexes)))
Run Code Online (Sandbox Code Playgroud)
itertools中有一个"切片"迭代器.它模拟了我们在python中熟悉的切片操作.您正在寻找的是类似于此的东西:
myList = [0,1,2,3,4,5]
firstValue = myList[:1]
Run Code Online (Sandbox Code Playgroud)
迭代器使用itertools的等价物:
from itertools import islice
def MyGenFunc():
for i in range(5):
yield i
mygen = MyGenFunc()
firstValue = islice(mygen, 0, 1)
print firstValue
Run Code Online (Sandbox Code Playgroud)