我有两个字典列表,当某个键匹配时,我希望它将第一个列表中的dict追加到第二个字典中,但是当字典变大时,它需要很长时间。有更快的方法吗?
with open('tables', 'rb') as fp:
tables = pickle.load(fp)
# embedding
for table in tables:
filename = table + "_constraints"
with open(filename, 'rb') as fp:
fkeys = pickle.load(fp)
if fkeys and len(fkeys) == 1:
key = fkeys[0][1]
rkey = fkeys[0][2]
rtable = fkeys[0][3]
filename = table + ".json"
with open(filename, 'rb') as fp:
child = list(json.load(fp))
filename = rtable + ".json"
with open(filename, 'rb') as fp:
parent = list(json.load(fp))
for dict in child:
for rdict in parent:
if dict[key] == rdict[rkey]:
if "embed_"+table not in rdict:
rdict["embed_"+table] = []
del dict[key]
rdict["embed_"+table].append(dict)
break
输入示例为:
tables = [child, parent]
child = [{child_id : 1, child_name : matthew , parent_id: 1},
{child_id : 2, child_name : luke , parent_id: 1},
{child_id : 3, child_name : mark , parent_id: 2}]
parent = [{parent_id:1, parent_name: john},
{parent_id:2, parent_name: paul},
{parent_id:3, parent_name: titus}]
输出为:
parent = [{parent_id:1, parent_name: john, child_embed:[{child_id : 1, child_name : matthew },{child_id : 2, child_name : luke}]},
{parent_id:2, parent_name: paul, chiled_embed : [{child_id : 3, child_name : mark}]},
{parent_id:3, parent_name: titus}]
答案 0 :(得分:0)
如果我正确阅读了问题,这应该可以满足您的需求...
for entry in child:
p_id = entry['parent_id']
parent_update = [x for x in parent if x['parent_id'] == p_id][0]
position = parent.index(parent_update)
del entry['parent_id']
if 'child_embed' in list(parent_update.keys()):
parent_update['child_embed'] = parent_update['child_embed'] + [entry]
else:
parent_update['child_embed'] = [entry]
parent[position] = parent_update
print(parent)
给出:
[{'parent_id': 1, 'parent_name': 'john', 'child_embed': [{'child_id': 1, 'child_name': 'matthew'}, {'child_id': 2, 'child_name': 'luke'}]}, {'parent_id': 2, 'parent_name': 'paul', 'child_embed': [{'child_id': 3, 'child_name': 'mark'}]}, {'parent_id': 3, 'parent_name': 'titus'}]
答案 1 :(得分:0)
当您像这样循环时:
for dict in child:
for rdict in parent:
您正在设置O(n²)操作。对于每个孩子,您都可以搜索每个父母。给定1000个孩子和1000个父母,大约有100万循环。当然,您可以早点休息,但不会改变函数相对于列表中数字的增长率。 p>
您应该花时间制作一个对象,无论对象多大,它都可以使您以相同的速度找到所需的对象。在Python中,这是dict
。您可以通过一个循环将父列表变成字典:
>> parent_d = {d['parent_id']: {'name': d['parent_name']} for d in parent}
>> print(parent_d)
{1: {'name': 'john'}, 2: {'name': 'paul'}, 3: {'name': 'titus'}}
这使您可以查找父母,而不必每次都遍历整个列表:
>> parent_d[1]
{'name': 'john'}
有了这个功能,您就可以遍历孩子们一次,然后将其添加到父母中(如果密钥是新的,使用setdefault
是初始化列表的便捷方法)
for d in child:
parent = parent_d[d['parent_id']]
parent.setdefault('child_embed', []).append({'child_id' : d['child_id'], 'child_name' : d['child_name'] })
现在您有了一个清晰的字典,其中所有信息都键入了parent:
{ 1: {'name': 'john','child_embed': [{'child_id': 1, 'child_name': 'matthew'},{'child_id': 2, 'child_name': 'luke'}]},
2: {'name': 'paul', 'child_embed': [{'child_id': 3, 'child_name': 'mark'}]},
3: {'name': 'titus'}}
这是一种不错的格式。如果您需要返回列表以匹配旧格式,则可以使用列表理解:
>> [{'parent_id':i, **rest} for i, rest in parent_d.items()]
[{'parent_id': 1,
'name': 'john',
'child_embed': [{'child_id': 1, 'child_name': 'matthew'},
{'child_id': 2, 'child_name': 'luke'}]},
{'parent_id': 2,
'name': 'paul',
'child_embed': [{'child_id': 3, 'child_name': 'mark'}]},
{'parent_id': 3, 'name': 'titus'}]