比较另外两个字典列表时,更新字典列表中的字典

时间:2019-07-31 16:41:03

标签: python list dictionary

我有两个字典列表,当某个键匹配时,我希望它将第一个列表中的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}]

2 个答案:

答案 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万循环。当然,您可以早点休息,但不会改变函数相对于列表中数字的增长率。

您应该花时间制作一个对象,无论对象多大,它都可以使您以相同的速度找到所需的对象。在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'}]