使用字典推导反转一对多映射


lst = [{'272': '4', '273': '4', '274': '4', '275': '5'}]
dct = {}
for k, v in lst[0].items():
if dct.get(v) is None:
dct.update({v: [k]})
else:
dct[v].append(k)

输出:

{'4': ['272', '273', '274'], '5': ['275']}

我也可以写一个嵌套的推导式:

dct = {v: [k for (k, v1) in lst[0].items() if v1 == v]
for (k, v) in lst[0].items()}

输出相同:

{'4': ['272', '273', '274'], '5': ['275']}** 

但是我们可以尝试通过在字典推导中使用单个for循环来获得相同的结果吗?

在字典理解中无法一步完成相同的操作。您可以有效地反转字典,但由于在原始字典中没有1对1的映射,因此需要为每个值聚合重复的键。

问题中的列表是转移注意力的东西。我将使用
d = {'272': '4', '273': '4', '274': '4', '275': '5'}

您可以采用几种方法。同样的方法是保持循环,但要稍微简化它。例如,您可以使用collections.defaultdict,它类似于常规的dict,只是它允许您自动设置缺失的键为空值:

from collections import defaultdict
result = defaultdict(list)
for k, v in d.items():
result[v].append(k)

如果使用几个标准库函数,则可以为此编写一个推导式。一种方法是使用itertools.groupby,但这需要您先应用sorted:

from itertools import groupby
from operator import itemgetter
result = {k: list(map(itemgetter(0), vs))
for k, vs in groupby(sorted(d.items(),
key=itemgetter(1, 0)),
itemgetter(1))}

operator.itemgetter的工作原理与lambda x: x[0]类似,但速度更快,效率更高。

对于第二个解决方案,请注意,由于排序,时间复杂度从O(n)变为O(n log n),并且您牺牲了许多易读性,只是为了拥有"单行"。

使用临时帮助字典的hack:

dct = {v: h.setdefault(v, [k])
for h in [{}]
for k, v in lst[0].items()
if v not in h or h[v].append(k)}

相关内容

  • 没有找到相关文章

最新更新