2016-11-24 25 views
8

最近我遇到了這個問題字符串:在刪除列表中的項目優雅的方式,它不具有出現在另一個列表

說有我要處理的事情的清單:

process_list=["/test/fruit/apple","/test/fruit/pineapple","/test/fruit/banana","/test/tech/apple-pen","/test/animal/python","/test/animal/penguin"] 

我想用另一個列表中排除的東西,比如:

exclude_list=["apple","python"] 

的process_list應該是這樣的我套用exclude_list給它(包含蘇任何process_list項目後, B:

["/test/fruit/banana","/test/animal/penguin","/test/fruit/pineapple"] 

,或者如果exclude_list是: exclude_list=["pen","banana"]

的process_list應該是這個應用過濾器後:

["/test/fruit/apple","/test/fruit/pineapple","/test/animal/python"] 

所以我試圖在第一個是:

for item in exclude_list: 
    for name in (process_list): 
     if item in name: 
      process_list.remove(name) 

當然這不起作用,因爲刪除元素s從列表中重複使用for循環時不允許。代碼只刪除了第一個匹配,然後停止。

於是我想出了一個方法與另一個列表要做到這一點:

deletion_list=[] #Track names that need to be deleted 
for item in exclude_list: 
    for name in (process_list): 
     if item in name: 
      deletion_list.append(name) 
# A list comprehension 
process_list=[ x for x in process_list if x not in deletion_list ] 

它的工作原理,但我的膽量告訴我,有可能是一個更優雅的方式。現在需要另一個列表來存儲需要刪除的名稱。有任何想法嗎?

回答

14

您可以使用使用all()濾波器列表理解表達爲:

# Here: `p` is the entry from `process_list` 
#  `e` is the entry from `exclude_list` 

>>> [p for p in process_list if all(e not in p for e in exclude_list)]        
['/test/fruit/banana', '/test/animal/penguin'] 

關於你的語句:

當然,這並沒有工作,因爲從刪除元素列表,而使用for循環遍歷它是不允許的。代碼只刪除了第一個匹配,然後停止。

你可以有遍歷列表的副本:

for item in list(exclude_list): # OR, for item in exclude_list[:]: 
#    ^-- Creates new copy ----------------------------^   
+4

我更喜歡'...如果所有(e不在p ...)'更清楚地表達語義,但是我召集的主要是品味問題。 – gboffi

+0

謝謝,它越來越優雅!順便說一下,我建議你在你的答案中保留'any()'和'all()'版本。我更喜歡'all()'版本,但是誰知道,有人可能會喜歡'any()'版本。 – zyc

+1

@zyc:看起來好像每個人都是在第一個地方複製了「我沒有提到的」。每個人都已經有了答案。如果有人想探索,他們可能會找到它。在我看來,不是提到所有的選擇,而是最好展示正確的方式來做到這一點。太多的選擇只會造成混亂 –

1
[line for line in lines if not any(word in line for word in words)] 
2

使用os.path.basename獲得路徑的基本名稱,使用內置的functon all檢查的基本部分是未包含在exclude_list中。

import os 

process_list=["/test/fruit/apple","/test/fruit/pineapple","/test/fruit/banana","/test/tech/apple-pen","/test/animal/python","/test/animal/penguin"] 

# Case 1 
exclude_list=["apple","python"] 

l = [s for s in process_list 
     if all(item not in os.path.basename(s) for item in exclude_list)] 

print(l) 
['/test/fruit/banana', '/test/animal/penguin'] 

# Case 2 
exclude_list=["pen","banana"] 

l = [s for s in process_list 
     if all(item not in os.path.basename(s) for item in exclude_list)] 

print(l) 
['/test/fruit/apple', '/test/fruit/pineapple', '/test/animal/python'] 
0

如果您想直接與process_list,沒有任何有趣的行爲,你應該用一個拷貝,這是這樣創建的工作列表理解的工作:process_list [:]

process_list=["/test/fruit/apple","/test/fruit/pineapple","/test/fruit/banana","/test/tech/apple-pen","/test/animal/python","/test/animal/penguin"] 
exclude_list=["apple","python"] 
process_list = [x for x in process_list[:] if not any(y in x for y in exclude_list)] 
1

另一種方法來達到你想要的是如下:

[item for item in process_list if not any(exc in item.split('/')[-1] for exc in exclude_list)] 

輸出:

>>> [item for item in process_list if not any(exc in item.split('/')[-1] for exc in exclude_list)] 
['/test/fruit/banana', '/test/animal/penguin'] 
4

此外,您還可以使用正則表達式,例如

import re 

pattern = '(' + ('|').join(exclude_list) + ')' 
list(filter(lambda l : re.search(pattern,l) == None, process_list)) #filter will return iterator in case if you use python 3 
相關問題