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

时间:2019-01-09 11:13:35

标签: python dictionary for-loop optimization

我想基于同一个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中)?如果是(我怀疑,基于所需的时间),也许有一种方法可以对其进行优化?

3 个答案:

答案 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