繁体   English   中英

python:根据另一个dict列表过滤dict列表

[英]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 元素中的关键特征是id11,22,33priority1,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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM