2011-06-19 160 views
6

過濾器/映射等同於列表理解嗎? 假設我有以下功能過濾器映射vs列表理解

def fib_gen(): 
    a,b = 0,1 
    yield 0 
    yield 1 
    while True: 
     a,b = b,a+b 
     yield b 

現在我可以用列表解析列出FIB編號:

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

假設我想只列出甚至謊數字。我會使用過濾器/地圖執行以下操作:

a = fib_gen() 
print filter(even, map(lambda x: a.next(), range(int(sys.argv[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] 
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),我們就可以處理你的序列。

+0

感謝。如何在我的例子中過濾包含next()的表達式? –

+0

@Oleg:哦,我添加一些信息,檢查我最新的添加,你會發現你也可以避免'next'。 – Skurmedel

1

我不是這件事將與發電機一起工作。爲了與列表理解這項工作,你需要有:

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

這將返回:

[1, 3, 13, 55, 233] 

問題是你需要訪問列表中,但第二次的下一個號碼一個。next()調用使得它應該做什麼,即得到下一個數字。據我所知,不可能將a.next()的值與列表理解一起使用兩次。

+0

它是可能的,但你必須嵌套在'print [n for n,i in((a.next(),i)for i in range(int(sys.argv [1])))if even(n )]','n'是'a.next()'並且被使用兩次。 –

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

你可以使用下面的代碼:

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

這是一個特殊情況,因爲每個第三fibbonacci數是偶數。

0

您可以隨時生成偶數FIBO數字只有太...

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