Python 使用同一键将多个字典的值添加到另一个字典的正确方法

Python 使用同一键将多个字典的值添加到另一个字典的正确方法,python,dictionary,for-loop,optimization,Python,Dictionary,For Loop,Optimization,我想基于相同的键将3个不同字典的3个不同值添加到1个“all_in_one”字典中 我有3个基于相同文本语料库的大型词典(其中每个文件都包含来自同一行(实际上是多行)的值,但列不同)。所有3个字典都有相同的键 它们看起来像这样: tokens = {"token1": 10, "token2": 56, "token3": 90, ...} lemmas = {"token1": "lemma1", "token2": "lemma2", "token2": "lemma3", ...} c

我想基于相同的
将3个不同字典的3个不同
添加到1个“all_in_one”字典中

我有3个基于相同文本语料库的大型词典(其中每个文件都包含来自同一行(实际上是多行)的
值,但列不同)。所有3个字典都有相同的

它们看起来像这样:

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]], ... } 
我想将这些值添加到另一个字典中,使其看起来像这样:

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]
问题是,它可以工作(不知道是否正常),但文件量很小。我有500k的档案。我没有尝试使用最终的语料库运行它,因为即使是第一次尝试使用100个文件也需要几个小时,而且还没有完成(100个文件=6500个标记,所以我假设是6500^3个循环…)。我只测试了10和20个文件


这是否是一个正确的循环(将3个dic的值添加到另一个dic)?如果是(我怀疑,基于所需的时间),也许有办法优化它?

我的回答假设这三本词典的键都是相同的。在这种情况下,我认为这里不需要3个循环。你只需要一个for循环。由于键是相同的,并且您只需要将相同键的值组合在一起,您可以简单地循环字典的任何一个键并执行以下操作

all_in_one = {}

for tk, tv in tokens.items():
    all_in_one[tk] = [tv, lemmas[tk], categs[tk]]

由于所有字典中的键都是相同的,因此可以使用字典理解对其中任何一个字典的键进行迭代。要减少重复逻辑,可以使用
运算符.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}

如果三个字典之间的键不相同,您可以在此处使用:

还可以使用“设置交点”提取相同的关键点:

{k: [tokens.get(k), lemmas.get(k), categs.get(k)] for k in tokens.keys() & lemmas.keys() & categs.keys()}

如果由于某种原因字典没有相同的键,这也可以防止引发
keyrerror

如果某些键在所有字典中都不存在,可能会发生什么情况?@buran,OP指定了
所有3个字典都有相同的键
,但RoadRunner的回答涵盖了放松这一假设的情况。在上述情况下,它们都存在于所有3个字典中,但你的问题让我觉得我构建得不恰当。我想我需要重写它,所以引理是关键值,
引理
字典应该包括每个引理的标记嵌套字典,每个标记出现。。。谢谢大家!@jpp,对不起,但是“所有字典都有相同的键”并不意味着“并且只有这些/相同的键”。当我问这个问题时,RoadRunner的答案不存在。@buran,很公平,所有的答案都陈述了潜在的假设,所以我认为我们没有损失(太多)在翻译中。值得指出的是,如果字典中的键并不总是相等的,这是最好的答案。@jpp我已经包括了一个集合交集示例,如果键相同,它也适用。我忽略了OP提出的所有3个字典都具有相同的键假设。如果所有键都相同,则无需进行交叉,只需迭代其中一个字典(任何一个都可以)。@jpp这是真的,但如果出于某种原因,并非所有字典都具有相同的键,使用这种方法会产生一个
键错误
。谢谢,这个解决方案工作得非常快(和下面的解决方案一样,谢谢@jpp)。我的循环显然是新手循环。但我仍然需要重写@buran的评论中提到的整个内容。