我想基于同一个values
将3个不同词典中的3个不同key
添加到1个“ all_in_one”字典中。
我有3个基于相同文本语料库的大词典(其中每个文件都包含来自同一行的values
,实际上是这些文件的多行,但它们的不同列) 。所有3个词典的key
都相同。
它们看起来像这样:
tokens = {"token1": 10, "token2": 56, "token3": 90, ...}
lemmas = {"token1": "lemma1", "token2": "lemma2", "token2": "lemma3", ...}
categs = {"token1": "categX", "token2": "categY", "token3": "categZ", ...}
我想将这些值添加到另一个字典中,使其看起来像这样:
all_in_one = {"token1": [tokens[value1], lemmas[value1], categs[value1]],
"token2": [tokens[value2], lemmas[value2], categs[value2]], ... }
我有这样一个循环:
all_in_one = {}
for tk, tv in tokens.items():
for lk, lv in lemmas.items():
for ck, cv in categs.items():
if tk == lk == ck:
all_in_one[tk] = [tv, lv, cv]
问题是,它可以工作(不知道是否还可以),但是文件数量很少。我有50万个文件。尚未尝试使用最终的语料库运行它,因为即使是第一次尝试处理100个文件也要花费几个小时并且没有完成(100个文件= 6500个令牌,所以我认为它是6500 ^ 3循环...)。我只用10和20个文件进行了测试。
这样做是否是正确的循环(将3个dic的值添加到另一个dic中)?如果是(我怀疑,基于所需的时间),也许有一种方法可以对其进行优化?
答案 0 :(得分:3)
我的答案假设所有三个词典都具有完全相同的键。在那种情况下,我认为这里不需要3个for循环。您只需要一个for循环。由于键是相同的,并且您只需要将相同键的值组合在一起,就可以简单地循环使用字典中的任何键并执行
all_in_one = {}
for tk, tv in tokens.items():
all_in_one[tk] = [tv, lemmas[tk], categs[tk]]
答案 1 :(得分:2)
由于所有词典中的键均相同,因此您可以使用字典理解来迭代这些词典中的任何一个的键。要减少重复的逻辑,可以使用operator.itemgetter
:
from operator import itemgetter
tokens = {"token1": 10, "token2": 56, "token3": 90}
lemmas = {"token1": "lemma1", "token2": "lemma2", "token3": "lemma3"}
categs = {"token1": "categX", "token2": "catehY", "token3": "categZ"}
all_in_one = {k: list(map(itemgetter(k), (tokens, lemmas, categs))) for k in tokens}
# {'token1': [10, 'lemma1', 'categX'],
# 'token2': [56, 'lemma2', 'catehY'],
# 'token3': [90, 'lemma3', 'categZ']}
其他替代方法包括使用列表理解来显式定义或列表:
# define list explicitly
all_in_one = {k: [tokens[k], lemmas[k], categs[k]] for k in tokens}
# use list comprehension
all_in_one = {k: [lst[k] for lst in (tokens, lemmas, categs)] for k in tokens}
答案 2 :(得分:2)
如果所有三个词典之间的键都不相同,则可以在此处使用collections.defaultdict()
:
from collections import defaultdict
tokens = {"token1": 10, "token2": 56, "token3": 90}
lemmas = {"token1": "lemma1", "token2": "lemma2", "token3": "lemma3"}
categs = {"token1": "categX", "token2": "catehY", "token3": "categZ"}
result = defaultdict(list)
for d in (tokens, lemmas, categs):
for k, v in d.items():
result[k].append(v)
print(result)
# defaultdict(<class 'list'>, {'token1': [10, 'lemma1', 'categX'], 'token2': [56, 'lemma2', 'catehY'], 'token3': [90, 'lemma3', 'categZ']})
此外,您也可以将itertools.chain
压缩为上述内容:
from itertools import chain
for k, v in chain(tokens.items(), lemmas.items(), categs.items()):
result[k].append(v)
print(result)
# defaultdict(<class 'list'>, {'token1': [10, 'lemma1', 'categX'], 'token2': [56, 'lemma2', 'catehY'], 'token3': [90, 'lemma3', 'categZ']})
您还可以使用设置的交集提取相同的关键点:
{k: [tokens.get(k), lemmas.get(k), categs.get(k)] for k in tokens.keys() & lemmas.keys() & categs.keys()}
如果字典由于某些原因没有相同的键,这还会阻止引发KeyError
。