我有一个返回以下字典的函数
abc= {"type":"insecure","id":"1",
"name":"peter","s_count":"2",
"b_count":"1", "s_1_name":"melisa",
"s_1_id":"2","s_2_name":"graham",
"s_2_id":"4", "b_1_name":"henrik",
"b_1_id": "9"}
我想通过以下方式查找字典:
xyz={"type":"insecure","id":"1",
"name":"peter",
"s" : [{"id" : "2", "name": "melisa"},
{"id" : "4", "name": "graham"}],
"b" : [{"id" : "9", "name": "henrik"}]}
逻辑如下:如果字典中有s_count,则创建一个列表,其中包含以s开头的所有值。例如在我的例子中创建一个包含不同字典的列表,每个字典包含s_name和s_id,例如在我的例子中,结果列表中有两个字典:
"s" : [{"id" : "2", "name": "melisa"},{"id" : "4", "name": "graham"}]
如果b_count计数存在,也用b做同样的事。
有人可以帮我解决这个问题吗?
答案 0 :(得分:4)
我使用辅助函数:
from itertools import groupby
from operator import itemgetter
def extract_keys(mapping, prefix):
prefix = '{}_'.format(prefix)
# test for the `.._count` key first, if it's not there, bail out early
if prefix + 'count' not in mapping:
return None
# find all matching keys, split out the counter for sorting and grouping
keys = [(k, int(k.split('_', 2)[1]))
for k in mapping if k.startswith(prefix) and k != prefix + 'count']
keys.sort(key=itemgetter(1))
# group keys on the counter, then generate a dictionary per counter value
return [{k[0].split('_', 2)[-1]: mapping[k[0]] for k in group}
for c, group in groupby(keys, itemgetter(1))]
此功能通过前缀
提取密钥>>> extract_keys(abc, 's')
[{'id': '2', 'name': 'melisa'}, {'name': 'graham', 'id': '4'}]
>>> extract_keys(abc, 'b')
[{'name': 'henrik', 'id': '9'}]
使用该功能创建新词典或现场转换现有词典:
xyz = {k: v for k, v in abc.iteritems() if not k.startswith('s_') and not k.startswith('b_')}
s_values = extract_keys(abc, 's')
if s_values is not None:
xyz['s'] = s_values
b_values = extract_keys(abc, 'b')
if b_values is not None:
xyz['b'] = b_values
这会将您的abc
示例输入转换为:
>>> pprint(xyz)
{'b': [{'id': '9', 'name': 'henrik'}],
'id': '1',
'name': 'peter',
's': [{'id': '2', 'name': 'melisa'}, {'id': '4', 'name': 'graham'}],
'type': 'insecure'}
答案 1 :(得分:0)
我对它进行了一些改进,使其变得更加灵活。
def extract_keys(mapping, prefix):
prefix = "{}_".format(prefix)
# test for the `.._count` key first, if it's not there, bail out early
if prefix + "count" not in mapping:
return None
# find all matching keys, split out the counter for sorting and grouping
keys = [(k, int(k.split("_", -1)[-2])) for k in mapping if k.startswith(prefix) and k != prefix + "count"]
keys.sort(key=itemgetter(1))
# group keys on the counter, then generate a dictionary per counter value
return [{k[0].split("_", -1)[-1]: mapping[k[0]] for k in group} for c, group in groupby(keys, itemgetter(1))]
考虑以下字典。
abc= {"type":"insecure","id":"1",
"name":"peter","s_a_count":"2",
"b_count":"1", "s_a_1_name":"melisa",
"s_a_1_id":"2","s_a_2_name":"graham",
"s_a_2_id":"4", "b_1_name":"henrik",
"b_1_id": "9"}
使用该功能创建新词典或现场转换现有词典:
xyz = {k: v for k, v in abc.iteritems() if not k.startswith('s_a') and not k.startswith('b_')}
s_values = extract_keys(abc, 's_a')
if s_values is not None:
xyz['s_a'] = s_values
b_values = extract_keys(abc, 'b')
if b_values is not None:
xyz['b'] = b_values
和转换后的输出是:
print xyz
{'b': [{'id': '9', 'name': 'henrik'}],
'id': '1',
'name': 'peter',
's_a': [{'id': '2', 'name': 'melisa'}, {'id': '4', 'name': 'graham'}],
'type': 'insecure'}