2011-05-18 101 views
16

如何找到滿足特定標準的序列中的對象? 列表理解和過濾器遍歷整個列表。 是手工製作的唯一選擇嗎?python序列查找功能

mylist = [10, 2, 20, 5, 50] 
find(mylist, lambda x:x>10) # returns 20 
+0

你的意思是你只想找到符合條件的第一個對象? – Blair 2011-05-18 03:08:17

+0

對於多個對象,你應該做'[我爲我在mylist如果我> 10]' – JBernardo 2011-05-18 03:11:13

+0

@Blair和@JBernardo,是的,只有第一個匹配的對象。 – Salil 2011-05-18 03:18:41

回答

22

這裏是我使用模式:

mylist = [10, 2, 20, 5, 50] 
found = next(i for i in mylist if predicate(i)) 

或者,在Python 2.4/2.5,next()是不是內置:

found = (i for i in mylist if predicate(i)).next() 

請注意,next()引發StopIteration如果沒有元素爲找到。在大多數情況下,這可能是好的,你要求第一個元素,不存在這樣的元素,所以程序可能無法繼續。

如果,另一方面,你知道在這種情況下做的,你可以提供一個默認next():

conf_files = ['~/.foorc', '/etc/foorc'] 
conf_file = next((f for f in conf_files if os.path.exists(f)), 
       '/usr/lib/share/foo.defaults') 
+0

你自己拿出來還是你在某處看過它,如果是的話,在哪裏?另外,使用內置的'next'並且傳遞默認值(在這種情況下可能是空列表)可能會更好嗎? – 2013-10-02 09:56:12

+1

'next()'已經在Python 2.6中引入 - http://docs.python.org/2.6/library/functions.html?highlight=next#next – 2013-10-02 19:55:16

+0

@Piotr:我認爲這可能取決於特定的用例。如果你想要一個空序列的第一個元素,沒有正確的值返回,它沒有第一個元素。提出例外情況可能非常有意義。 'bool(foo(next(filter(foo,[]),[]))!= True',也就是說,除非'foo'類似於'lambda x:x == []''和'[]''在*'[]'中肯定不是*,所以在任何情況下都是謊言。 – SingleNegationElimination 2013-10-02 22:31:35

5

如果你只是想比10的第一較大,您可以使用itertools.ifilter

import itertools 
first_gt10 = itertools.ifilter(lambda x: x>10, [10, 2, 20, 5, 50]).next() 

如果希望所有大於10%,這可能是最簡單的使用list-comprehension

all_gt10 = [i for i in mylist if i > 10] 
7

實際上,在Python 3中,至少過濾器不會遍歷整個列表。

要仔細檢查:

def test_it(x): 
    print(x) 
    return x>10 

var = next(filter(test_it, range(20))) 

在Python 3.2,打印出0-11,並指定VAR至11

在Python的2.X版本中,你可能需要使用itertools。 IFilter的。

+0

呼叫良好; 'zip','map'和'filter'在Python3中都變得很懶惰。 (替換爲Python2的'imap','izip'和'ifilter'。) – bernie 2011-05-18 03:26:34

0

懶得寫:

mylist = [10, 2, 20, 5, 50] 
max(mylist, key=lambda x: x>10)