2011-12-16 41 views
110

前面的愚蠢問題:我想要一種習慣方式來查找列表中與謂詞相匹配的第一個元素。找到與謂詞相匹配的序列中的第一個元素

當前的代碼是相當難看:

[x for x in seq if predicate(x)][0] 

我想過將其更改爲:

from itertools import dropwhile 
dropwhile(lambda x: not predicate(x), seq).next() 

但一定是有什麼更優雅......那將是很好的,如果它返回一個None值,而不是在找不到匹配項時引發異常。

我知道我可以只定義諸如函數:

def get_first(predicate, seq): 
    for i in seq: 
     if predicate(i): return i 
    return None 

但它是相當雞肋開始填充這樣的效用函數(和人的代碼可能不會注意到,他們已經在那裏,所以他們往往會隨着時間的推移重複),如果有內置的插件已經提供相同的。

+1

這不是一個愚蠢的問題,而@ j-f-sebastian:這不是重複的。這個問題具體是關於返回一個對象,並返回`None`而不是拋出異常。這也是關於優雅。另一個問題更多的是一個問題,並沒有提出這些問題,至少不是很清楚。 – 2017-03-06 16:05:30

+1

除了被後來問不是「[蟒蛇序列查找功能(https://stackoverflow.com/questions/6039425/python-sequence-find-function)」,這個問題有一個**更好的標題**。 – Wolf 2017-07-20 10:23:19

回答

159

next(x for x in seq if predicate(x))

它提出StopIteration如果是沒有的。

next(ifilter(predicate, seq), None)

返回None如果不存在這樣的元件。

+12

或者你可以爲`next`提供第二個「default」參數,而不是引發異常。 – 2011-12-16 12:50:27

+2

@fortran:[`下一個()`](http://docs.python.org/library/functions.html#next)可因爲Python 2.6,您可以閱讀[最新消息頁面(HTTP://文檔。 python.org/whatsnew/2.7.html)快速熟悉新功能。 – jfs 2011-12-16 13:02:10

68

你可以使用一個發電機表達默認值,然後next它:

next((x for x in seq if predicate(x)), None) 

雖然這一個班輪你需要使用Python> = 2.6。

這篇頗受歡迎的文章進一步討論了這個問題:Cleanest Python find-in-list function?

3

我不認爲在你的問題中提出的解決方案有什麼問題。

在我自己的代碼,我會實現它這樣雖然:

(x for x in seq if predicate(x)).next() 

()的語法創建一個發電機,這比用[]一次生成所有的列表更有效。

1

J.F.塞巴斯蒂安的答案是最優雅的,但需要python 2.6 fortran指出。

對於Python版本< 2。6,這是我能拿出最好的:

from itertools import repeat,ifilter,chain 
chain(ifilter(predicate,seq),repeat(None)).next() 

或者,如果你需要一個名單後(列表處理的StopIteration),或者你需要的不僅僅是第一更,但仍然不是全部,你可以做到這一點islice:

from itertools import islice,ifilter 
list(islice(ifilter(predicate,seq),1)) 

UPDATE: 雖然我個人使用)第一(稱爲預定義的函數,捕捉一個StopIteration和返回None,這裏的一個可能的改進在上述的例子:避免使用濾波器/的IFilter:

from itertools import islice,chain 
chain((x for x in seq if predicate(x)),repeat(None)).next() 
相關問題