我正在使用API的几个端点,它返回的数据非常详细。我想将这些数据的一部分提供给其他地方的另一段代码。
假设我有几个这样的词典(我计划循环并过滤):
asset = {
'id': 1,
'name': 'MY-PC',
'owner': 'me',
'location': 'New York City',
'model': {
'id': 1,
'name': 'Surface',
'manufacturer': {
'id': 1,
'name': 'Microsoft'
}
}
}
我想创建一个将该字典带入的函数,以及一个“掩码”,它将用于创建仅允许的项目的新字典。这可能是一个示例掩码(但是,我可以使用任何格式使得结果代码最简洁):
mask = {
'id': True,
'name': True,
'model': {
'id': True,
'name': True,
'manufacturer': {
'name': True
}
}
}
然后该函数应该返回:
mask = {
'id': 1,
'name': 'MY-PC',
'model': {
'id': 1,
'name': 'Surface',
'manufacturer': {
'name': 'Microsoft'
}
}
}
Python 3中是否已经内置了有助于此的内容?看起来如果我必须手动执行此操作,它会很快变得非常难看。我发现itertools.compress
,但这似乎是列表,不会处理字典的复杂性。
答案 0 :(得分:3)
您可以通过仅选择主要字典中对应的值来从掩码中递归构建新的dict:
def prune_dict(dct, mask):
result = {}
for k, v in mask.items():
if isinstance(v, dict):
value = prune_dict(dct[k], v)
if value: # check that dict is non-empty
result[k] = value
elif v:
result[k] = dct[k]
return result
print(prune_dict(asset, mask))
{'id': 1,
'model': {'id': 1, 'manufacturer': {'name': 'Microsoft'}, 'name': 'Surface'},
'name': 'MY-PC'}
答案 1 :(得分:2)
这是一个使用递归的好机会,这里有一些我没有测试的示例代码:
def copy(asset, result, mask):
for key_name, value in mask.items():
if value == True:
result[key_name] = asset[key_name]
else:
result[key_name] = x = {}
copy(asset[key_name], x, value)
y = {}
copy(asset, y, mask)
答案 2 :(得分:0)
这可能是一个递归函数。此外,对于面具,我建议使用以下格式:mask = ["id", "name", "model.id", "model.name", "model.manufacturer.name"]
然后,您首先只保留在掩码中命名的条目:
def filterstage1(dictionary, mask):
result = {}
for key in dictionary:
if isinstance(dictionary[key], dict):
newmask = [maskname[mask.find(".") + 1:] for maskname in mask if maskname.startswith(key + ".")]
result[k] = filterstage1(dictionary[key], newmask)
elif key in mask:
result[key] = dictionary[key]
return result
然后,根据您是否要删除不在掩码中且没有子元素的子词典,您可以包括第二阶段:
def filterstage2(dictionary, mask):
result = {}
for key in dictionary:
if not (isinstance(dictionary[key], dict) and dictionary[key] == {} and key not in mask):
result[key] = dictionary[key]
最终代码:filterstage2(filterstage1(dictionary, mask), mask)
。如果您愿意,可以将两个阶段组合在一起。