在列表推导中对itertools.groupby对象的if条件总是返回False

编程语言 2026-07-09

我得到了一个包含以下结构的文件列表:

[output-input]_[A-Z]_foo_bar_[0-n].pkl 的n 值不同

file_list = [
 'output_A_foo_bar_0.pkl',
 'output_A_foo_bar_1.pkl',
 'output_A_foo_bar_2.pkl',
 'output_A_foo_bar_3.pkl',
 'output_B_foo_bar_0.pkl',
 'output_B_foo_bar_1.pkl',
 'output_B_foo_bar_2.pkl',
 'output_B_foo_bar_3.pkl',
 'output_G_foo_bar_1.pkl',
 'output_H_foo_bar_0.pkl',
 'output_H_foo_bar_1.pkl',
 'input_A_foo_bar_0.pkl',
 'input_H_foo_bar_0.pkl',
 'input_H_foo_bar_1.pkl',
 'input_H_foo_bar_2.pkl',
 'input_H_foo_bar_3.pkl']

我想要的:

[['output_A_foo_bar_0.pkl',
 'output_A_foo_bar_1.pkl',
 'output_A_foo_bar_2.pkl',
 'output_A_foo_bar_3.pkl',],
['output_B_foo_bar_0.pkl',
 'output_B_foo_bar_1.pkl',
 'output_B_foo_bar_2.pkl',
 'output_B_foo_bar_3.pkl']
]

我尝试了这个:

file_list = [
 'output_A_foo_bar_0.pkl',
 'output_A_foo_bar_1.pkl',
 'output_A_foo_bar_2.pkl',
 'output_A_foo_bar_3.pkl',
 'output_B_foo_bar_0.pkl',
 'output_B_foo_bar_1.pkl',
 'output_B_foo_bar_2.pkl',
 'output_B_foo_bar_3.pkl',
 'output_G_foo_bar_1.pkl',
 'output_H_foo_bar_0.pkl',
 'output_H_foo_bar_1.pkl',
 'input_A_foo_bar_0.pkl',
 'input_H_foo_bar_0.pkl',
 'input_H_foo_bar_1.pkl',
 'input_H_foo_bar_2.pkl',
 'input_H_foo_bar_3.pkl']

res = [list(i) 
 for j, i in itertools.groupby(file_list, lambda a: a.rsplit('_', maxsplit=1)[0])
 if ('output' in j) and (sum(1 for x in i) == 4)
]

print(res)

结果: [[],[]]

还有这个:

file_list = [
 'output_A_foo_bar_0.pkl',
 'output_A_foo_bar_1.pkl',
 'output_A_foo_bar_2.pkl',
 'output_A_foo_bar_3.pkl',
 'output_B_foo_bar_0.pkl',
 'output_B_foo_bar_1.pkl',
 'output_B_foo_bar_2.pkl',
 'output_B_foo_bar_3.pkl',
 'output_G_foo_bar_1.pkl',
 'output_H_foo_bar_0.pkl',
 'output_H_foo_bar_1.pkl',
 'input_A_foo_bar_0.pkl',
 'input_H_foo_bar_0.pkl',
 'input_H_foo_bar_1.pkl',
 'input_H_foo_bar_2.pkl',
 'input_H_foo_bar_3.pkl']

res = [list(i) 
 for j, i in itertools.groupby(file_list, lambda a: a.rsplit('_', maxsplit=1)[0])
 if ('output' in j) and (len(list(i)) == 4)
]

print(res)

结果: [[],[]]

但在这两种情况中,if 语句的第二部分(在itertools对象 i 上)总是 False。我肯定遗漏了什么,但我还想不出到底是什么。

解决方案

你当前代码中对对象类型有一些混用,并且在两个版本中都存在一个问题:你对由 groupby 返回的组(你的 j)的使用。它不是一个列表,而是一个迭代器,因此如果你尝试在第二次使用它时(比如在 list(j) 之类的地方)它就会被耗尽。

我们不能用它第一次来得到长度,再用第二次来创建一个列表。所以,我们要么在后续按长度过滤,要么在第一次遍历分组时就使用 := 的赋值来创建一个列表(也就是在 if 子句中——它会先执行,然后列表再被加入输出中)。

我也建议不要把太多内容放进那个大型的列表推导式,在尝试分组之前就过滤掉有效的文件名(如果其中一个文件的格式无效,你的代码就会失败)。

所以,你可以这样做:

from itertools import groupby
import re

file_list = [
 'output_A_foo_bar_0.pkl',
 'output_A_foo_bar_1.pkl',
 'output_A_foo_bar_2.pkl',
 'output_A_foo_bar_3.pkl',
 'output_B_foo_bar_0.pkl',
 'output_B_foo_bar_1.pkl',
 'output_B_foo_bar_2.pkl',
 'output_B_foo_bar_3.pkl',
 'output_G_foo_bar_1.pkl',
 'output_H_foo_bar_0.pkl',
 'output_H_foo_bar_1.pkl',
 'input_A_foo_bar_0.pkl',
 'input_H_foo_bar_0.pkl',
 'input_H_foo_bar_1.pkl',
 'input_H_foo_bar_2.pkl',
 'input_H_foo_bar_3.pkl']

# we filter the valid filenames *before* trying to group them,
# so we can be sure that a valid key will exist
valid_pattern = re.compile(r"output_[A-Z]_")
# we filter with a generator expression, no intermediate list will be created
valid_names = (f for f in file_list if valid_pattern.match(f))


out = [lst for key, grp in groupby(valid_names, key=lambda x: x.split('_')[1])
           if len(lst:=list(grp))==4]



print(out)

输出:

[['output_A_foo_bar_0.pkl', 
'output_A_foo_bar_1.pkl', 
'output_A_foo_bar_2.pkl', 
'output_A_foo_bar_3.pkl'], 

['output_B_foo_bar_0.pkl', 
'output_B_foo_bar_1.pkl', 
'output_B_foo_bar_2.pkl', 
'output_B_foo_bar_3.pkl']]

在没有 := 赋值的较旧版本的Python中,你可以,例如这样做:

res = (list(grp) for key, grp in groupby(valid_names, key=lambda x: x.split('_')[1]))

out = [l for l in res if len(l)==4]
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章