2017-04-04 45 views
3

我想更好地理解列表解析是如何工作的。 我有以下函數返回true或false,如果一個數是素數(我發現某處的論壇,但不記得在哪裏):有條件的列表理解

import math 

def is_prime(n): 
    if n % 2 == 0 and n > 2: 
     return False 
    for i in range(3, int(math.sqrt(n)) + 1, 2): 
     if n % i == 0: 
      return False 
    return True 

如果我運行:

[x for x in range(2, num) if is_prime(x)] 

我得到在試圖將整個功能轉換到一個列表理解所期望的結果

[2, 3, 5, 7, 11, 13, 17, 19] 

我想出了:

[x if not (x%2==0 and x > 2) else x for x in range (2, num) 
    for i in range(3, int(x**(1/2))+1, 2) if not (x%i==0)] 

主要生產:

[10, 11, 13, 14, 16, 17, 19] 

不知道我要去的地方錯了,希望得到一些幫助。事實上,我認爲在這種情況下使用函數會更好,但正如我所說的,我正在嘗試理解列表理解及其能力。

+0

@Wright:剛剛返回奇數和排除2. OP也排除可被3整除的數字。 – Prune

+0

我會說它太多以至於無法擠入列表理解。練習可以,但是當其他人閱讀時不要這樣做。 –

+0

只爲咯咯我定時每個版本:函數'[x爲範圍內的x(2,數量),如果is_prime(x)]'版本是每循環** 9.01 s **; @Julien版本(稍作修改):**每循環12.8 s **和@Harshit Garg版本:**每循環44.4 s **。 –

回答

2

你可以這樣做:

[n for n in range(2, num) if n % 2 != 0 and n > 2 and all(n % i != 0 for i in range(3, int(math.sqrt(n)) + 1, 2))] 

雖然一個班輪只是爲了它的緣故未必是好事。使用像你這樣的主要測試功能的IMO更好...

注意:在您的嘗試中不起作用的是您修改了外部列表理解的邏輯。你仍然需要像[n for n in range(...) if (expression testing if n is prime)]這樣的結構。

+1

我修改了一點,在列表中包含'2':'[n代表範圍內的(2,num),如果(n%2!= 0或n == 2)以及所有(n%i!= 0)在範圍內(3,int(math.sqrt(n))+ 1,2))]'。不確定我完全理解答案的工作原理,但不包括'2',但會再看一些。 –

+0

我同意這個功能是更好的方法。對於我來說,這是一個練習,可以更好地理解列表解析。我想如果我能理解複雜的東西,它會幫助我理解更簡單更合適的用法。 –

+0

不錯的地方,我確實忘了否定'n> 2'到'n == 2'。 – Julien

0

主要問題是你正在做一個複雜的翻譯。嘗試簡化原始條件,以便返回「x if x == 2,否則x ...」,就像您已經完成的那樣。我只是給你一個主要的提示,從你已經做的,我認爲你可以弄明白。

如果不是,請嘗試簡化「else」表達式,以便了解該子句的邏輯。那麼我相信你會得到它。你做得很好。

0

上面的代碼中存在邏輯錯誤 1/2評估爲0,而不是0.5。要做到這一點,要麼使用0.5或1/2.0或1.0/2

此外,它並沒有照顧2作爲特殊情況。作爲(for i in range(3, int(x**(1/2.0))+1, 2) if not (x%i==0))不執行

for i in range(3, int(x**(1/2.0))+1, 2) if not (x%i==0)也是一個邏輯上的錯誤作爲每當這個情況是真實的,它會導致增加

多個條目正確的方法是

[x for x in range (2, num) if x == 2 or (x > 2 and x % 2 == 1 and len([i for i in range(3, int(x**(1/2.0))+1, 2) if x%i == 0 ])==0)] 
+0

我在Python 3中,'(1/2)'爲我評估爲'0.5',不知道你說的問題是否在老版本的Python中,但是,你的答案確實有效 –