2010-05-24 83 views
34

我有一個整數列表,我需要計算它們中有多少個> 0.
我目前正在做一個列表解析,看起來像這樣:使用Python列表解析計算列表中的正整數元素

sum([1 for x in frequencies if x > 0]) 

這似乎是一個體面的理解,但我不喜歡「1」;它似乎有點神奇的數字。有沒有更Pythonish的方式來做到這一點?

+2

計數非零元素是不一樣的計數元件> 0的標題應相應修改 – joaquin 2010-05-24 20:51:23

+0

我更新了問題的標題,以便它反映其內容。我希望這對你很好。 – EOL 2010-05-26 07:28:13

回答

63

如果你想減少內存量,就可以避免使用發電機產生的臨時列表:

sum(x > 0 for x in frequencies) 

這工作,因爲boolint一個子類:

>>> isinstance(True,int) 
True 

True的值爲1:

>>> True==1 
True 

然而,正如Joe Golton在評論中指出的那樣,這種解決方案並不是非常快。如果您有足夠的內存來使用中間臨時列表,則sth's solution可能會更快。下面是一些比較計時的各種解決方案:

>>> frequencies = [random.randint(0,2) for i in range(10**5)] 

>>> %timeit len([x for x in frequencies if x > 0]) # sth 
100 loops, best of 3: 3.93 ms per loop 

>>> %timeit sum([1 for x in frequencies if x > 0]) 
100 loops, best of 3: 4.45 ms per loop 

>>> %timeit sum(1 for x in frequencies if x > 0) 
100 loops, best of 3: 6.17 ms per loop 

>>> %timeit sum(x > 0 for x in frequencies) 
100 loops, best of 3: 8.57 ms per loop 

謹防timeit結果可能取決於Python的,操作系統或硬件的版本而異。

當然,如果你是數字的大名單上做數學,你或許應該使用NumPy的:

>>> frequencies = np.random.randint(3, size=10**5) 
>>> %timeit (frequencies > 0).sum() 
1000 loops, best of 3: 669 us per loop 

的NumPy的陣列需要比同等的Python列表較少的內存,並且可以進行計算表現比任何純Python解決方案都快得多。

+2

變化:[x> 0 for x in頻率] .count( True) – 2010-05-24 20:38:08

+3

@Peter:注意你的建議在數據上循環兩次;一次構建輸出列表,兩次計算真值。 – tzot 2010-06-24 19:16:57

+0

@ΤΖΩΤΖΙΟΥ:是的,當然,感謝您的信息! – 2010-06-24 19:20:20

6

你可以過濾列表上使用len()

len([x for x in frequencies if x > 0]) 
+2

甚至更​​好,使用發電機(帶[和]) – 2010-05-24 20:34:11

+1

您可以使用此過濾器使其看起來更清晰。 len(filter(lambda x:x> 0,頻率)) – 2010-05-24 20:35:22

+2

@valya:這對於一個生成器不起作用 – sth 2010-05-24 20:50:38

18

稍微更Python的方法是使用一個發電機來代替:

sum(1 for x in frequencies if x > 0) 

這就避免了調用sum()之前生成的整個列表。

+0

+1,因爲這是一種常被忽視的理解方式。如果您在函數調用中評估列表理解,可以省略'[]'。 – jathanism 2010-05-24 20:43:25

+0

如果沒有任何元素符合條件,則中斷。 – FogleBird 2011-08-08 20:04:55

+0

@FogleBird:空發生器的'sum()'返回0. – 2011-08-08 20:20:01

0

這個怎麼樣?

reduce(lambda x, y: x+1 if y > 0 else x, frequencies)

編輯: 與接受答案的靈感來自@〜unutbu:

reduce(lambda x, y: x + (y > 0), frequencies)

+0

我希望我得到了一個評論,用那個投票去學習我的錯誤。請? – 2010-05-24 20:39:50

+0

似乎有一種從lambda函數轉向列表解析的趨勢。 – fairfieldt 2010-05-28 23:31:44

+1

我不是一個讓你失望的人;然而我會認爲人們傾向於「減少」,它被淘汰等(由Guido宣言)。我喜歡'reduce',但是在這種情況下我也不喜歡它的使用,因爲'sum(x> 0 ...)'變體對我來說似乎更直接。 – tzot 2010-06-24 19:20:55

4

這工作,但加入bool S作爲int S可以是危險的。請用一粒鹽代碼(可維護性先行):

sum(k>0 for k in x) 
+2

作爲整數添加布爾值可以保證在Python 2和3中工作:http://stackoverflow.com/questions/2764017/is-false-0-and-true-1-in-python-an-implementation-detail-or儘管如此,保證金爲 – EOL 2010-05-26 07:30:47

+0

+1。 :) – EOL 2010-05-26 07:31:03

0

如果數組僅包含大於等於0的元素(即,所有的元素都是0或正整數),那麼你可以只計數零和減去該號碼形成陣列的長度:

len(arr) - arr.count(0)