过滤地图与列表理解

时间:2011-06-19 14:07:18

标签: python

过滤器/地图是否等同于列表理解? 假设我有以下功能

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]))))

如何使用列表推导得到相同的结果?

6 个答案:

答案 0 :(得分:13)

  

过滤器/地图是否等同于列表理解?

是的,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)

答案 1 :(得分:9)

您可以使用生成器存储中间结果,并在其上“过滤”。

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]

答案 2 :(得分:6)

filtermap很容易转换为列表理解。

这是一个基本的例子:

[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

对序列进行切片
print itertools.islice(gen, int(sys.argv[1]))

这避免了在理解本身中使用next的需要。只要您不尝试评估无限序列(就像我们在列表推导中省略islice那样),我们就可以使用您的序列。

答案 3 :(得分:1)

我不认为这适用于发电机。为了使这项工作与列表理解,你需要:

print [a.next() for i in range(int(sys.argv[1])) if even(a.next())]

返回:

[1, 3, 13, 55, 233]

问题是您需要访问列表中下一个数字的两倍,但第二个a.next()调用会使它应该执行的操作,即获取下一个数字。据我所知,不可能将带有列表推导的a.next()值存储两次。

答案 4 :(得分:1)

您可以使用以下代码:

a = fib_gen()
print [a.next() for i in range(int(sys.argv[1])) if i%3==0]

这是一个特殊情况,因为每个第三个fibbonacci数是偶数。

答案 5 :(得分:0)

您也可以始终生成均匀的fibo数字......

def evenfib():
    """ Generates the even fibonacci numbers """
    a, b = 2, 0
    while True:
        a, b = b, a+4*b
        yield a