将字典值映射到另一个字典的最佳方法是什么?

4
我想知道将两个字典合并成一个新字典的最佳方法,如下所示: dict1 = {k1: v1, k2: v2, ...}dict2 = {v1: w1, v2: w2, ...}合并为 result = {k1: w1, k2: w2, ...} 我已经有了使用字典推导式的解决方案:
result = {
   k: dict2[v]
   for k, v in dict1.items()
}

但我认为这不是最优雅的方法。你能帮我吗?


6
我认为你的列表推导式很好。 - tobias_k
3
如果您知道每个v项都在dict2中,那么这是一个非常好的解决方案。如果不在,就要看您希望程序如何反应来解决它了。 - Maarten Fabré
2个回答

4

对于双字典情况,您的字典解析很好。这假定您可以保证在dict1中的值是dict2中的键。

考虑如何将其扩展到任意字典输入,您可以使用一个for循环:

dict1 = {'k1': 'v1', 'k2': 'v2'}
dict2 = {'v1': 'w1', 'v2': 'w2'}
dict3 = {'w1': 'x1', 'w2': 'x2'}

def chainer(first, *others):
    res = first.copy()  # make a copy to avoid overwriting dict1
    for k, v in res.items():
        for dct in others:
            v = dct[v]
        res[k] = v
    return res

res = chainer(dict1, dict2, dict3)
# {'k1': 'x1', 'k2': 'x2'}

1
我不想打断你的回答,但我想发布类似的内容,但现在有点多余了。使用reduce,尝试这种替代形式如何? return {k: reduce(lambda x, d: d[x], other, v) for k, v in first.items()} - tobias_k
1
@tobias_k,好的,是的,我一直在努力弄清楚reduce版本,可以单独发布一个答案...有些人可能喜欢函数式编程。性能差异将是有趣的(尽管可读性也很重要)。 - jpp

4

作为一种替代/扩展,与@jpp的答案相比,您也可以使用reduce/functools.reduce来获取稍微压缩一些的chainer函数形式:

from functools import reduce
def chainer(first, *others):
    return {k: reduce(lambda x, d: d[x], others, v) for k, v in first.items()}

这两种方法哪个更好主要是取决于个人口味;使用和结果都是相同的。

对于只有两个字典的情况,你的字典推导式在我看来非常好和优雅。不过,你可能需要使用get或者添加一个条件,以防第二个字典中不存在某个键。

>>> dict1 = {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
>>> dict2 = {'v1': 'w1', 'v2': 'w2'}
>>> {k: dict2.get(v, 'undefined') for k, v in dict1.items()}
{'k1': 'w1', 'k2': 'w2', 'k3': 'undefined'}
>>> {k: dict2[v] for k, v in dict1.items() if v in dict2}
{'k1': 'w1', 'k2': 'w2'}

像这样在chainer中添加这样的保护措施有一些复杂,特别是对于使用reduce的这种变体(可能根本不需要)。


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