2011-04-06 167 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"]