我有一个包含文件的列表(它们的路径)。
我写了一个这样的函数来删除与模式匹配的某些文件,但它最多只删除了2个文件,我不明白为什么。
remove_list = ('*.txt',) # Example for removing all .txt files in the list
def removal(list):
for f in list:
if any(fnmatch(basename(f.lower()), pattern) for pattern in remove_list:
list.remove(f)
return list
//编辑;好的,在代码中命名我的列表“列表”是个坏主意。在我的代码中,它的调用方式不同。只想给我一个抽象的想法,我正在处理什么。应该提到
答案 0 :(得分:1)
在您迭代它时修改列表是一个坏主意,因为当行为未确定时,您可以非常容易地处理边缘情况。
做你想做的事情的最好方法是建立一个没有你不想要的项目的新名单:
remove_list = (r'*.txt',) # Example for removing all .txt files in the list
def removal(l, rm_list):
for f in l:
for pattern in rm_list:
if not fnmatch(basename(f.lower()), pattern):
yield f
print(list(removal(list_with_files, remove_list))
在这里,我展开您的any
单行,这可能会让您的代码看起来很聪明,但很难阅读,并且可能会让您在六个月内感到头痛。做一个简单的for
和if
会更好(因为更具可读性)!
yield
关键字将使函数返回python中名为a generator的内容,这样当您重复函数的结果时,它将返回值,使其可用于调用上下文,然后返回到函数以返回下一个项目。
这就是为什么在print语句中,我在函数调用周围使用list()
,而如果你遍历它,则不需要将它放在列表中:
for elt in removal(list_with_files, remove_list):
print(elt)
如果您不想使用生成器(以及yield
语句),那么您必须在返回之前手动构建列表:
remove_list = (r'*.txt',) # Example for removing all .txt files in the list
def removal(l, rm_list):
ret_list = []
for f in l:
for pattern in rm_list:
if not fnmatch(basename(f.lower()), pattern):
ret_list.append(f)
return ret_list
HTH
答案 1 :(得分:1)
如果您要根据扩展名删除 str.endswith ,则只需传递扩展的元组:
remove_tup = (".txt",".py") # Example for removing all .txt files in the list
def removal(lst):
return [f for f in lst if not f.endswith(remove_tup)]
答案 2 :(得分:0)
您提供的代码含糊不清
1.不使用list
它会影响内置list
2.在迭代时修改列表,你可以复制它
我的建议是: 您可以按如下方式迭代原始列表和remove_list:
test.py
list1=["file1.txt", "file2.txt", "other.csv"]
list2=["file1.txt", "file2.txt"] # simulates your remove_list
listX = [x for x in list1 if x not in list2] # creates a new list
print listX
$ python test.py
['other.csv']
答案 3 :(得分:0)
正如评论中所说的那样,在迭代它时不要修改列表。也可以像这样使用列表理解:
patterns = ('*.txt', '*.csv')
good = [f for f in all_files if not any(fnmatch(basename(f.lower()), pattern) for pattern in patterns)]