我有一个字典列表,我正在尝试为其编写一个过滤函数。过滤依据的参数将以字典的形式给出,其中关键字将是字符串(与要筛选的字典列表中的关键字匹配),值将是具有上限和下限的列表。
要过滤的字典示例列表:
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个键:值对。我需要能够根据任意数量的参数进行过滤,因为我并不总是希望指定每个参数的上限和下限,因此我没有对每个参数进行硬编码比较。
提前感谢所有人/任何帮助!
发布于 2020-11-17 17:35:17
这就是你要找的东西吗?
result = list(filter(lambda x: all(lower < x[key] < upper
for key, (lower, upper) in params.items()),
test_list))
发布于 2020-11-17 17:42:25
你在这段代码中有一个问题:
for target in filtered_list:
if target[k]>=v[0] and target[k]<=v[1]:
filtered_list.remove(target)
您正在从iterable Type中删除阻止您进行某些循环的项...这是一种过滤列表的方法,你最好这样做:
filtered_list = [target for target in filtered_list if target[k]<v[0] or target[k]>v[1]]
发布于 2020-11-17 17:57:51
你已经得到了答案,所以我只给你一些额外的解释。
首先,您的代码在迭代列表时从列表中删除了一项。所以它会忽略一些项目。例如,当您删除列表的第二项时。然后,它将在下一次循环中获得第四项。
我已经修改了你的原始代码,所以你可以理解它应该是什么。
首先,您可以使用复制而不是移动。
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
https://stackoverflow.com/questions/64872496
复制相似问题