2012-11-27 69 views
0

我在查找過濾列表中的元素。比較和過濾python中的列表元素

比方說我有一個列表:

listA = ['banana', 'apple', 'appleRed', 'melon_01', 'appleGreen', 'Orange', 'melon_03'] 
listB = ['apple', 'melon'] 

現在我需要比較列表,併產生只包含元素名稱與數組listB可以啓動一個列表。

結果應該是:

listResult = ['apple', 'appleRed', 'melon_01', 'appleGreen', 'melon_03'] 

我可以循環使用一個循環,如果做比較這2。像

for item in listA: 
    for fruit in listB: 
     if item.startswith(fruit): 
      listResult.append(item) 
      break 

但是,我想知道是否有任何捷徑可用於此操作,因爲這可能需要更多時間來進行大型列表比較。

回答

5

使用列表中理解和any發生器:

[item for item in listA if any(item.startswith(fruit) for fruit in listB)] 

或者,如正確地@DSM建議:

[item for item in listA if item.startswith(tuple(listB))] 

比第一個解決方案的方式更快,而且幾乎一樣快正則表達式@Iguananaut提出的解決方案(但更加緊湊和可讀):

In [1]: %timeit [item for item in listA if any(item.startswith(fruit) for fruit in listB)] 
100000 loops, best of 3: 4.31 us per loop 

In [2]: %timeit [item for item in listA if item.startswith(tuple(listB))] 
1000000 loops, best of 3: 1.56 us per loop 

In [3]: %timeit filter(regex.match, listA) 
1000000 loops, best of 3: 1.39 us per loop 
+3

'.startswith'也接受字符串作爲參數的元組,所以'如果item.startswith (元組(listB))'也會起作用。 – DSM

+1

要明確一點,雖然知道'.startswith'接受元組是很可愛的,但'any'的適用範圍要廣泛得多,因此它是知道和使用這些模式的重要因素。 – DSM

+0

謝謝。第二種解決方案看起來很棒 – karpanai

1
listResult = [ i for i in listA if any(i.startsWith(j) for j in listB) ] 
2

如果有相對較少的項目你listB你可以把它變成一個正則表達式相當有效:

import re 
regex = re.compile(r'^(?:%s)' % '|'.join(listB)) 
filter(regex.match, listA) 

就是這樣來到我的腦海裏的第一件事,但我認爲其他人將有其他的想法。

請注意,使用列表解析的其他答案當然是非常好的和合理的。我以爲你想知道是否有辦法讓它稍快一點。再次要強調這種解決方案可能並不總是對一般情況下快,但是在這種情況下,稍微:

In [9]: %timeit [item for item in listA if any(item.startswith(fruit) for fruit in listB)] 
100000 loops, best of 3: 8.17 us per loop 

In [10]: %timeit filter(regex.match, listA) 
100000 loops, best of 3: 2.62 us per loop 
+0

我同意你的意見 – karpanai