如何将Python字典列表转换为指定键对应剩余字典的映射?
问题:将字典列表转换为指定映射的最优写法?
假设有如下Python字典列表:
l = [ {"a": 10, "b": 100, "c": 100}, {"a": 20, "b": 100, "c": 100}, {"a": 30, "b": 100, "c": 100}, ]
已知每个字典中的键"a"对应的值是唯一的:
assert len({x["a"] for x in l}) == len(l)
希望生成以"a"的值为键、对应字典剩余内容为值的映射,最终结果如下:
{ 10: {"b": 100, "c": 100}, 20: {"b": 100, "c": 100}, 30: {"b": 100, "c": 100}, }
目前已写出如下代码:
{x["a"]: {k: v for k, v in x.items() if k != "a"} for x in l}
请问这是否是最优写法?是否有更优方式或遗漏的内置函数?
分析与解答
你的现有写法已经是非常简洁高效的Pythonic实现,时间复杂度为O(n*m)(n是列表长度,m是单字典键值对数量),这已经是这类转换的最优时间复杂度——毕竟每个元素都需要被遍历处理一次。
下面提供几种替代思路,各有适用场景:
1. 允许修改原字典时:用pop简化写法
如果后续不需要再使用原列表里的字典,可以直接用pop提取"a"的值作为键,剩下的字典直接作为值:
{x.pop("a"): x for x in l}
这种写法最简洁,但会直接修改原列表中的字典,有副作用,需要根据实际场景判断是否适用。
2. 保留键固定时:用itemgetter明确提取
如果需要保留的键是固定明确的(比如这里的"b"和"c"),可以结合operator.itemgetter来简化内层字典的构造:
from operator import itemgetter target_keys = ["b", "c"] get_target = itemgetter(*target_keys) {x["a"]: dict(zip(target_keys, get_target(x))) for x in l}
这种方式可读性更强,但灵活性不如原写法——如果字典的键不固定,原写法的通用性更好。
3. 追求可读性时:用普通循环实现
如果想让代码逻辑更直白,也可以用普通循环:
result = {} for d in l: key = d["a"] # 复制原字典并移除"a"键,避免修改原字典 result[key] = {k: v for k, v in d.items() if k != "a"}
这和你的原写法逻辑一致,但拆分后可读性更高,适合需要多人协作维护的场景。
总结
- 若不允许修改原字典,你最初的写法就是最优解:通用、简洁且无副作用。
- 若允许修改原字典,
{x.pop("a"): x for x in l}是最简洁高效的选择。
内容的提问来源于stack exchange,提问作者Johnny Metz
相关产品推荐
相关产品推荐

