2011-04-06 128 views
1

我有名爲files的列表中的目錄的所有文件名。我想過濾它,所以只保留.php擴展名的文件。從列表中刪除文件名python

for x in files: 
    if x.find(".php") == -1: 
     files.remove(x) 

但是,這似乎跳過文件名。我能做些什麼呢?

+2

您正在修改正在迭代的列表。這通常是一個壞主意(並且它是「跳過文件名」的原因)。 – 2011-04-06 19:33:33

回答

10

簡單的列表理解怎麼樣?

files = [f for f in files if f.endswith('.php')] 

或者如果你喜歡一臺發電機的結果:

files = (f for f in files if f.endswith('.php')) 
5
>>> files = ['a.php', 'b.txt', 'c.html', 'd.php'] 
>>> [f for f in files if f.endswith('.php')] 
['a.php', 'd.php'] 
1

大部分提供給定列表/發電機內涵的答案,這可能是你想要去90%的方式該時間,特別是如果你不想修改原始列表。

然而,對於這種情況,要修改的地方,我一般用下面的代碼片段原來的列表,(說的尺寸原因):

idx = 0 
while idx < len(files): 
    if files[idx].find(".php") == -1: 
     del files[idx] 
    else: 
     idx += 1 

至於爲什麼你原來的代碼是不工作 - 它在迭代器上更改列表...「for x in files」隱含地創建了一個迭代器,就像如果你完成了「for iter(files)」一樣,並且刪除列表中的元素會引起混淆迭代器的位置。對於這種情況,我一般使用上面的代碼,或者如果它發生了很多的項目,要素出來成一個函數,例如:

def filter_in_place(func, target): 
    idx = 0 
    while idx < len(target): 
     if func(target[idx)): 
      idx += 1 
     else: 
      del target[idx] 
+0

好的一點,這可能適用於非常大的列表或低端系統。 – 2011-04-08 14:31:54

0

過這個老問題只是偶然。這裏有許多解決方案可以完成這項工作,但是他們忽略了一個文件名可能只是「.php」的情況。我懷疑這個問題是關於如何過濾PHP腳本和「.php」可能不是一個PHP腳本。我建議的解決方案如下:

>>> import os.path 
>>> files = ['a.php', 'b.txt', 'c.html', 'd.php', '.php'] 
>>> [f for f in files if os.path.splitext(f)[1] == ".php"]