我有一个字典来自无限的子类别树结构。下面是示例;
{
"asset_id": 1566,
"asset_name": "asset1",
"asset_type": "A",
"assets": [
{
"asset_id": 1255,
"asset_name": "asset2",
"asset_type": "A",
"assets": [
{
"asset_id": 1472,
"asset_name": "asset3",
"asset_type": "A",
"assets": []
},
{
"asset_id": 1473,
"asset_name": "asset4",
"asset_type": "A",
"assets": []
}
]
},
{
"asset_id": 1257,
"asset_name": "asset5",
"asset_type": "A",
"assets": []
},
{
"asset_id": 1259,
"asset_name": "asset6",
"asset_type": "A",
"assets": []
},
{
"asset_id": 1493,
"asset_name": "asset7",
"asset_type": "A",
"assets": []
}
]
}
我想将所有项目都放在此树结构的一个类别下。 例如,“ asset_id” = 1255下的所有资产。
样本输出;
[
{
"asset_id": 1472,
"asset_name": "asset3",
"asset_type": "A",
"assets": []
},
{
"asset_id": 1473,
"asset_name": "asset4",
"asset_type": "A",
"assets": []
}
]
我该如何实现?
答案 0 :(得分:1)
您可以使用递归:
d = {'asset_id': 1566, 'asset_name': 'asset1', 'asset_type': 'A', 'assets': [{'asset_id': 1255, 'asset_name': 'asset2', 'asset_type': 'A', 'assets': [{'asset_id': 1472, 'asset_name': 'asset3', 'asset_type': 'A', 'assets': []}, {'asset_id': 1473, 'asset_name': 'asset4', 'asset_type': 'A', 'assets': []}]}, {'asset_id': 1257, 'asset_name': 'asset5', 'asset_type': 'A', 'assets': []}, {'asset_id': 1259, 'asset_name': 'asset6', 'asset_type': 'A', 'assets': []}, {'asset_id': 1493, 'asset_name': 'asset7', 'asset_type': 'A', 'assets': []}]}
def get_assets(_d, below = 1255):
if isinstance(_d, dict):
if _d['asset_id'] == below:
return _d['assets']
_r = list(filter(None, [get_assets(i, below) for i in _d['assets']]))
return _r[0] if _r else None
import json
print(json.dumps(get_assets(d), indent=4))
输出:
[
{
"asset_id": 1472,
"asset_name": "asset3",
"asset_type": "A",
"assets": []
},
{
"asset_id": 1473,
"asset_name": "asset4",
"asset_type": "A",
"assets": []
}
]
答案 1 :(得分:1)
如果您希望能够查找所有以key=value
格式指定的条件(例如asset_id=1255
)匹配的所有资产对象,那么这可能对您有用。
def retrieve_assets(struct, **kwargs):
def _rec(obj):
if type(obj) is dict:
if all(map(lambda k:obj.get(k) == kwargs.get(k), kwargs.keys())):
return [obj] #1
else:
return _rec(obj.get('assets')) #2
elif type(obj) is list:
filtered = []
for asset in obj:
filtered.extend(_rec(asset))
return filtered
return _rec(struct)
您这样称呼它:
retrieve_assets(tree, asset_id=1255)
它使用内部函数递归地测试所有嵌套资产是否满足给定条件(在kwargs
词典中作为键值对传递)。如果资产满足这些条件,它将全部返回给调用方(#1
,包装在列表中)。如果不是,则内部函数将重复进行以测试子资产列表(#2
)。
使用**kwargs
命名的参数扩展机制不仅可以指定'asset_id'字段,还可以指定查找条件。您最好发出如下所示的呼叫:
retrieve_assets(tree, asset_type='B', assets=[])
这样,您将获得asset_type
B
且没有任何子项的所有资产对象的列表(即,它们的asset
列表为空)自己。
编辑:在我答复之后,您明确表示只想检索满足指定条件的资产的后代资产。为了通过我的解决方案实现此目标,只需将标有#1
的行更改为:
return obj.get('assets') #1