在Python中合并两个defaultdict

4

我解析了一个庞大的文献记录数据库(约2000万条记录)。每个记录都有一个唯一的ID字段,一组作者和一组用于描述文献记录主要内容的术语/关键词。例如,典型的文献记录如下:

ID: 001
Author: author1
Author: author2
Term: term1
Term: term2

首先,我创建了两个 `defaultdict` 用于存储作者和术语:
d1 = defaultdict(lambda : defaultdict(list))
d2 = defaultdict(lambda : defaultdict(list))

接下来,我填充作者:

d1['id001'] = ['author1', 'author2'] 
d1['id002'] = ['author3'] 
d1['id003'] = ['author1', 'author4'] 

关键字:

d2['id001'] = ['term1', 'term2']  
d2['id002'] = ['term2', 'term3']
d2['id003'] = ['term4']

问题在于如何将这两个字典连接起来,以获取直接链接作者和术语的数据对象:
author1|term1,term2,term4
author2|term1,term2
author3|term2,term3
author4|term4

我有两个问题:

  • 这种方法是否合适,或者我应该以其他方式存储/表示数据?
  • 您能大致建议如何合并这两个字典吗?

2
你可以拥有一个多层字典并将作者和术语存储在同一个字典中吗?例如:d['id001']["authors"]=['author1', 'author2']; 和 d['id001']["terms"] = ['term1', 'term2'] - Raghuram
@Raghuram 是的,那样可以。 - Andrej
2个回答

5

这是一种方法。请注意,正如下面所示,您不需要使用嵌套字典或defaultdict来进行初始步骤。

from collections import defaultdict

d1 = {}
d2 = {}

d1['id001'] = ['author1', 'author2'] 
d1['id002'] = ['author3'] 
d1['id003'] = ['author1', 'author4'] 

d2['id001'] = ['term1', 'term2']  
d2['id002'] = ['term2', 'term3']
d2['id003'] = ['term4']

res = defaultdict(list)

for ids in set(d1) & set(d2):
    for v in d1[ids]:
        res[v].extend(d2[ids])

res = {k: sorted(v) for k, v in res.items()}

# {'author1': ['term1', 'term2', 'term4'],
#  'author2': ['term1', 'term2'],
#  'author3': ['term2', 'term3'],
#  'author4': ['term4']}

你不需要使用嵌套字典,你的意思是“你不需要使用默认字典”。 - Jean-François Fabre
@Jean-FrançoisFabre,两者都是!OP使用了d1 = defaultdict(lambda : defaultdict(list)) - jpp
是的,因为 OP 可能希望可以使用原始字典来构建结果。很好的解决方案,简洁明了 :) - Jean-François Fabre
@Jean-FrançoisFabre,谢谢,有很多方法可以做这件事。 - jpp

3
这些问题的关键在于从现有字典中构建“正确定向”的临时字典。一旦完成,就会更清晰(并且由于正确的字典查找而具有良好的复杂性)。
这是我的解决方案:
首先从d1创建一个dict author => ids。
然后创建结果(一个dict author => terms)。循环遍历已创建的author => ids dict,并使用d2的扁平化值填充结果。
d1=dict()
d2=dict()

d1['id001'] = ['author1', 'author2']
d1['id002'] = ['author3']
d1['id003'] = ['author1', 'author4']

d2['id001'] = ['term1', 'term2']
d2['id002'] = ['term2', 'term3']
d2['id003'] = ['term4']

import collections

authors_id = collections.defaultdict(list)
for k,v in d1.items():
    for a in v:
        authors_id[a].append(k)

print(dict(authors_id)) # convert to dict for clearer printing


authors_term = collections.defaultdict(list)
for k,v in authors_id.items():
    for a in v:
        for i in d2[a]:
            authors_term[k].append(i)

print(dict(authors_term)) # convert to dict for clearer printing

结果:

{'author4': ['id003'], 'author3': ['id002'], 'author1': ['id001', 'id003'], 'author2': ['id001']}
{'author3': ['term2', 'term3'], 'author4': ['term4'], 'author1': ['term1', 'term2', 'term4'], 'author2': ['term1', 'term2']}

1
小提示。不确定排序是否重要,但是如果重要,则此解决方案假定在循环ID时,作者的term4在term1之后。[可以轻松修复] - jpp
这个解决方案更像是一个“初步”解决方案,更容易理解,你的解决方案经过的步骤更少,显然更加精细和高效。 - Jean-François Fabre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接