我需要从另一个字典 (includes
) 中嵌套 id
来过滤字典列表 (relationships
)。这是我的实现:
def filter_includes(relationships, includes):
def normalize(data):
if data is None:
return []
return data if isinstance(data, list) else [data]
def simplify(r):
return ((d['type'], d['id']) for i in r for d in normalize(r[i]['data']))
r_set = set(simplify(relationships))
return [e for e in includes if (e['type'], e['id']) in r_set]
以下是通过的测试:
relationships = {
'author': {
'data': {
'type': 'users',
'id': '22DB1A00-0000-0000-00009BC6',
}
},
'parent': {
'data': {
'type': 'documents',
'id': 'BE7F4800-0000-0000-000021F6',
}
},
'pages_file': {
'data': None
},
'fields': {
'data': [
{
'type': 'dictionary',
'id': 'B15E5D00-0000-0000-000021F6-0001',
},
{
'type': 'dictionary',
'id': 'B15E5D00-0000-0000-000021F6-0002',
},
]
},
}
includes = [
{'type': 'users', 'id': '22DB1A00-0000-0000-00009BC6'},
{'type': 'dictionary', 'id': 'B15E5D00-0000-0000-000021F6-0002'},
{'type': 'dictionary', 'id': 'B15E5D00-0000-0000-000021F6-0003'},
]
def test_filter_includes():
result = filter_includes(relationships, includes)
assert len(result) == 2
assert result[0]['id'] == '22DB1A00-0000-0000-00009BC6'
assert result[1]['id'] == 'B15E5D00-0000-0000-000021F6-0002'
result = filter_includes({}, includes)
assert len(result) == 0
includes[0]['type'] = 'content_file'
includes[1]['type'] = 'content_file'
includes[2]['type'] = 'content_file'
result = filter_includes(relationships, includes)
assert len(result) == 0
includes[0]['type'] = 'documents'
includes[0]['id'] = 'BE7F4800-0000-0000-000021F6'
result = filter_includes(relationships, includes)
assert len(result) == 1
assert result[0]['type'] == 'documents'
assert result[0]['id'] == 'BE7F4800-0000-0000-000021F6'
澄清:过滤后我想得到的新字典应该与 id
中的嵌套字典具有相同的 type
和 relationships
。
总的来说,一切都足够好,filter_includes
函数按预期工作,但是我对更简洁的方法感兴趣。是否有更优雅\简洁的方法?