[英]python: filter list of dict based on another list of dict
我有两个字典列表。 让我们将第一个称为dd
:
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '3', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
dict 元素中的关键特征是id
即11,22,33
和priority
即1,2,3..
另一个dict
是过滤器dict
:
filter_dict = [{'11': 2}, {'33': 2}]
此过滤器dict
具有key-value
其中key
定义第一个dict
dd
中的id
,值表示要从第一个字典dd
中选择的元素数,即{'11': 2}
表示 select 基于dd
的前2
元素priority
。 并且,如果filter_dct
中没有相应的id
,则 select 只有 1 个来自dd
的最高优先级元素。
到目前为止,我所拥有的是一种基于priority
级从dd
中仅获取 1 个最高优先级元素的方法:
tmp = {}
for elem in dd:
tmp.setdefault([*elem][0], []).append(elem)
out = [subl[0] for subl in tmp.values()]
print(out)
我想要实现的所需 output :
res = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}}, # one elem because no record in the filter_dict
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}}]
编辑:
当元素超过 4 时,建议的解决方案会失败。
即对于输入:
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '4', 'channels': '35'}},
{'11': {'xx': '260', 'priority': '9', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '11', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
output 是:
[{'11': {'xx': '259', 'priority': '1', 'channels': '55'}}, {'11': {'xx': '270', 'priority': '11', 'channels': '35'}}, {'11': {'xx': '260', 'priority': '2', 'channels': '35'}}, {'22': {'xx': '300', 'priority': '1', 'channels': '40'}}, {'33': {'xx': '400', 'priority': '1', 'channels': '40'}}]
这是不正确的。
这对我有用:
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '3', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
filter_dict = [{'11': 2}, {'33': 2}]
res = []
for dd_one_dic in dd:
for dir_id, priority in dd_one_dic.items():
if priority['priority'] == '1':
res.append(dd_one_dic)
else:
for filter_one_dic in filter_dict:
if dir_id == list(filter_one_dic.keys())[0]:
if int(priority['priority']) <= filter_one_dic[list(filter_one_dic.keys())[0]]:
res.append(dd_one_dic)
print(*res, sep = '\n')
Output
{'11': {'xx': '259', 'priority': '1', 'channels': '55'}}
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}}
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}}
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}}
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}}
编辑:
这是一种更通用的方法,它也改变了格式
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '4', 'channels': '35'}},
{'11': {'xx': '260', 'priority': '9', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '11', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
filter_dict = [{'11': 2}, {'33': 2}]
res = []
middle_dict = {}
position = 0
first = True
def sortSecond(val):
return val[0]
for dd_one_dict in dd:
for dict_id, sub_dict in dd_one_dict.items():
if middle_dict.get(dict_id,False):
middle_dict[dict_id].append((int(sub_dict['priority']),position))
else:
middle_dict[dict_id] = [(int(sub_dict['priority']),position)]
position += 1
middle_dict[dict_id].sort(key = sortSecond)
external_counter = 0
for one_key in middle_dict.keys():
internal_counter = 2
for items in middle_dict[one_key]:
if first:
res.append({one_key:[dd[items[1]][one_key]]})
first = False
else:
for filter_one_dic in filter_dict:
if one_key == list(filter_one_dic.keys())[0]:
if internal_counter <= filter_one_dic[list(filter_one_dic.keys())[0]]:
res[external_counter][one_key].append(dd[items[1]][one_key])
internal_counter += 1
else:
break
first = True
external_counter += 1
print(res)
Output:
[{'11': [{'xx': '259', 'priority': '1', 'channels': '55'}, {'xx': '260', 'priority': '2', 'channels': '35'}]}, {'22': [{'xx': '300', 'priority': '1', 'channels': '40'}]}, {'33': [{'xx': '400', 'priority': '1', 'channels': '40'}, {'xx': '500', 'priority': '2', 'channels': '30'}]}]
不是很优雅,但这可以使用中间字典完成工作。
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '3', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
filter_dict = [{'11': 2}, {'33': 2}]
tmp = {k: d[k] for d in filter_dict for k in d} # {'11': 2, '33': 2}
out = []
for d in dd:
id = [*d][0]
if id not in tmp:
out.append(d)
tmp[id] = 0
elif tmp[id]:
out.append(d)
tmp[id] -= 1
else:
del tmp[id]
print(out)
[{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}}]
您可以使用defaultdict
来帮助您
from collections import defaultdict
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'11': {'xx': '270', 'priority': '3', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
res_each = defaultdict(list)
filter_dict = [{'11': 2}, {'33': 2}]
filter_map = {list(i.keys())[0]: list(i.values())[0] for i in filter_dict}
for i in dd:
res_each[list(i.keys())[0]].append(i)
res = []
for i in [sorted(v, key=lambda x: int(list(x.values())[0]['priority']))[:filter_map.get(k, 1)] for k, v in res_each.items()]:
res.extend(i)
print(res)
Output
[{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11':{'xx':'260','priority': '2', 'channels': '35'}},
{'22': {'xx': '300', 'priority': '1', 'channels':'40'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}}]
我假设dd根本没有排序。 我希望它有所帮助。
dd = [{'11': {'xx': '259', 'priority': '1', 'channels': '55'}},
{'11': {'xx': '270', 'priority': '3', 'channels': '35'}},
{'22': {'xx': '303', 'priority': '2', 'channels': '30'}},
{'33': {'xx': '400', 'priority': '1', 'channels': '40'}},
{'11': {'xx': '260', 'priority': '2', 'channels': '35'}},
{'33': {'xx': '500', 'priority': '2', 'channels': '30'}},
{'22': {'xx': '300', 'priority': '1', 'channels': '40'}},
{'33': {'xx': '606', 'priority': '3', 'channels': '30'}}]
# firstly sorted by key, then sorted by priority
dd = sorted(dd, key=lambda e: (list(e.keys())[0], int(list(e.values())[0]['priority'])))
filter_dict = [{'11': 2}, {'33': 2}]
filter_dict = {k:v for elem in filter_dict for k,v in elem.items()}
res = []
for i in dd:
key = list(i.keys())[0]
if key in filter_dict:
if filter_dict[key] > 0:
res.append(i)
filter_dict[key] -= 1
else:
res.append(i)
filter_dict[key] = 0
for i in res:
print(i)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.