2012-06-01 24 views
0

試圖創建一個文件列表,其中包含多個要在其上迭代的擴展名的文件列表。堆棧溢出的大部分答案都涉及使用lambda進行過濾,但我不確定在這種情況下它是如何工作的(僅僅是因爲迭代的設置方式)。到目前爲止,我有Python:從使用過濾器更尷尬的列表中刪除多個值

import fnmatch 

excluded = ['*.py', '*.py~'] 

fileNames = [] 

for fileName in os.listdir('.'): 
    fileNames.append(fileName) 
    print fileNames 

for p in excluded: 
    if fnmatch.fnmatch(fileName, p): 
     fileNames.remove(fileName) 
     print fileNames 

顯然問題是,list.remove只會刪除第一個實例,而不是所有實例。你認爲解決這個問題最有效的方法是什麼?

謝謝!

+0

你可能不是要吝嗇打印報表。否則,每次添加內容時都會再次打印整個列表。 – Matt

回答

4

使用列表理解)):

filtered = [x for x in os.listdir('.') if not any(fnmatch.fnmatch(x, p) for p in excluded)] 

另外,使用正則表達式更緊湊代碼:

filtered = [x for x in os.listdir('.') if not re.search(r'\.py~?$', x)] 

或者乾脆使用endswith

excluded = ('.py', '.py~') 
filtered = [x for x in os.listdir('.') if not x.endswith(excluded)] 
+1

最後一個可能是最好的。 – Matt

2

使用list comprehension

for p in excluded: 
    fileNames = [filename for filename in fileNames if not fnmatch.fnmatch(filename, p)] 

您可以通過使用any()以及這樣做更漂亮:

fileNames = [filename for filename in fileNames if not any(fnmatch.fnmatch(filename, p) for p in excluded)] 

注意,你可以將這個名單是沒有意義的,爲os.listdir()返回一個列表無論如何,你只需要做fileNames = os.listdir()就可以得到相同的結果 - 甚至可以將它放在列表理解中:

fileNames = [filename for filename in os.listdir() if not any(fnmatch.fnmatch(filename, p) for p in excluded)] 

如果您想在編制列表時編輯這些值,那麼您也可以使用列表理解功能來執行此操作。

另一種替代方案是fnmatch模塊有fnmatch.filter()

2
def includefilename(fileName): 
    for ex in excluded: 
     if fnmatch.fnmatch(fileName, ex): 
      return False 
    return True 

fileNames = [fileName for fileName in fileNames if includefilename(fileName)] 
+1

您也可以反轉該函數並將最後一行更改爲'fileNames = filter(includefilename,fileNames)'。 – Matt

+0

@Matt - 夠正確!改變。 –