[英]filter map vs list comprehension
过滤器/地图是否等同于列表理解? 假设我有以下功能
def fib_gen():
a,b = 0,1
yield 0
yield 1
while True:
a,b = b,a+b
yield b
现在我可以使用list comprehension列出fib数:
a = fib_gen()
print [a.next() for i in range(int(sys.argv[1]))]
假设我只想列出偶数的fib数。 我会使用filter / map执行以下操作:
a = fib_gen()
print filter(even, map(lambda x: a.next(), range(int(sys.argv[1]))))
如何通过列表理解获得相同的结果?
过滤器/地图是否等同于列表理解?
是的, map(f, L)
相当于[f(x) for x in L]
。 filter(f, L)
相当于[x for x in L if f(x)]
。 但是,由于具有副作用的列表推导通常很糟糕(在这里你修改了生成器的状态),你可以使用itertools
来获得更清洁的解决方案:
a = fib_gen()
a = itertools.islice(a, int(sys.argv[1]))
a = itertools.ifilter(even, a)
print list(a)
您可以使用生成器来存储中间结果,并在其上“过滤”。
fibs = (a.next() for i in whatever)
even_fibs = [num for num in fibs if num % 2 == 0]
或者在一行中:
even_fibs = [num for num in (a.next() for i in whatever) if num % 2 == 0]
请注意,如果要从迭代器中获取一定数量的元素,可以使用itertools.islice
:
from itertools import islice
fibs_max_count = int(sys.argv[1])
even_fibs = [num for num in islice(fib_gen(), fibs_max_count) if num%2 == 0]
filter
和map
很容易转换为列表理解。
这是一个基本的例子:
[hex(n) for n in range(0, 100) if n > 20]
这相当于:
list(map(hex, filter(lambda x: x > 20, range(0, 100))))
在我看来,理解更具可读性。 但是,如果条件变得非常先进,我更喜欢filter
。
所以在你的情况下:
[n for n in itertools.islice(fib_gen(), 100) if even(n)]
我在这里使用了islice
,因为序列是无限的。 但是如果使用生成器表达式,它也会成为无限流:
gen = (n for n in fib_gen() if even(n))
现在你可以使用islice
对序列进行islice
:
print itertools.islice(gen, int(sys.argv[1]))
这避免了在理解本身中使用next
的需要。 只要您不尝试评估无限序列(就像我们在列表islice
中省略了islice
那样),我们就可以使用您的序列。
我不认为这适用于发电机。 为了使这个工作与列表理解,你需要有:
print [a.next() for i in range(int(sys.argv[1])) if even(a.next())]
返回:
[1, 3, 13, 55, 233]
问题是您需要访问列表中下一个数字的两倍,但第二个a.next()调用会使它应该执行的操作,即获取下一个数字。 据我所知,不可能将带有列表推导的a.next()值存储两次。
您可以使用以下代码:
a = fib_gen()
print [a.next() for i in range(int(sys.argv[1])) if i%3==0]
这是一个特殊的情况,因为每个第三个fibbonacci数是偶数。
您也可以始终生成均匀的fibo数字......
def evenfib():
""" Generates the even fibonacci numbers """
a, b = 2, 0
while True:
a, b = b, a+4*b
yield a
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.