按值的上限/下限筛选字典列表



我有一个字典列表,我正试图为其编写筛选函数。要筛选的参数将以字典的形式给出,其中键将是字符串(与要筛选的字典列表中的键匹配(,值将是具有上限和下限的列表。

要筛选的词典列表示例:

test_list = [{'hello':1, 'goodbye':4}, {'hello':7, 'goodbye':6}, {'hello': 4, 'goodbye': 2}]

过滤参数示例:

params = {'hello':[1, 6], 'goodbye':[5, 8]}

我写的函数如下:

def filter_list(target_list, **kwargs):
filtered_list = target_list
for k,v in kwargs.items():
for target in filtered_list:
if target[k]<v[0] or target[k]>v[1]:
filtered_list.remove(target)
return filtered_list

由于某种原因,第二个参数没有被检查,我得到的输出是:

filter_it = filter_list(test_list, **params)
print(filter_it)
>>[{'hello': 4, 'goodbye': 2}]

为什么会这样?据我估计,字典清单上的任何一项都不应该通过标准。但如果我将参数更改为:

params = {'hello':[1, 8], 'goodbye':[5, 8]}

现在的输出是:

>>[{'hello': 7, 'goodbye': 6}]

将要使用的实际数据是一个约2500个字典的列表,每个字典约有45-50个键:值对。我需要能够通过任意数量的参数进行筛选,因为我并不总是想指定每个参数的上限和下限,因此我不硬编码每个参数的比较。

提前感谢您的帮助!

这就是您想要的吗?

result = list(filter(lambda x: all(lower < x[key] < upper 
for key, (lower, upper) in params.items()),
test_list))

您在这段代码中有一个问题:

for target in filtered_list:
if target[k]>=v[0] and  target[k]<=v[1]:
filtered_list.remove(target)

您正在从可迭代类型中删除阻止您执行某些循环的项。。。这是一种过滤列表的方法,你最好这样做:

filtered_list = [target for target in filtered_list if target[k]<v[0] or target[k]>v[1]]

您已经得到了答案,所以我只为您提供一些额外的解释。

首先,您的代码从列表中删除一个项目,同时对列表进行迭代。所以它会忽略一些项目。例如,当您删除列表的第二个项目时。然后它将在下一个循环中获得第四个项目。

我已经修改了你的原始代码,所以你可以理解它应该是什么。

首先,您可以使用复制而不是移动。

def filter_list_with_copy(target_list, **kwargs):
filtered_list = []
for target in target_list:
all_satisfied = True
for k, v in kwargs.items():
if target[k] < v[0] or target[k] > v[1]:
all_satisfied = False
break
if all_satisfied:
filtered_list.append(target)
return filtered_list

其次,您可以使用while而不是for。然后可以控制循环索引。

def filter_list_with_while(target_list, **kwargs):
filtered_list = target_list
for k, v in kwargs.items():
filtered_index = 0
filtered_list_length = len(filtered_list)
while filtered_index < filtered_list_length:
target = filtered_list[filtered_index]
if target[k] < v[0] or target[k] > v[1]:
filtered_list.remove(target)
filtered_list_length = len(filtered_list)
else:
filtered_index += 1
return filtered_list

最新更新