Python字典分组的优雅之道:告别繁琐的if/else
在数据处理中,一个极其常见的任务是按类别对项目进行分组,最典型的实现就是 {'类别A': [项目1, 项目2], '类别B': [项目3]} 这种值为列表的字典结构。
经典问题
当我们向这个字典添加新项目时,必须先判断类别(键)是否存在。如果不存在,需要先创建一个空列表,然后才能追加。
传统的做法是这样的:
data = {}
words = ['apple', 'ant', 'ball', 'banana']
for word in words:
key = word[0] # 按首字母分组
if key not in data:
data[key] = [] # 如果键不存在,先创建空列表
data[key].append(word)
# data -> {'a': ['apple', 'ant'], 'b': ['ball', 'banana']}
这段代码虽然能用,但 if 判断显得有些累赘。Python 提供了两种更优雅的方式来处理。
方法一:通用利器 dict.setdefault()
setdefault() 是普通字典自带的一个方法,完美契合此场景。
核心思想: d.setdefault(key, default_value) 会查找 key。如果 key 不存在,它会设置 d[key] = default_value;无论如何,它最后总会返回 d[key] 的值。
这意味着,我们总能得到一个列表,然后直接追加元素。
代码实现:
data = {}
words = ['apple', 'ant', 'ball', 'banana']
for word in words:
key = word[0]
# 一行代码完成检查、创建和获取列表的操作
data.setdefault(key, []).append(word)
这行代码完全替代了之前的 if 块,简洁而高效。
适用场景: 对任何已存在的普通字典进行此类操作时的最佳选择。
方法二:专家之选 collections.defaultdict
如果你要从零开始构建一个用于分组的字典,defaultdict 是更专业的选择。
核心思想: 在创建 defaultdict 时,你指定一个“工厂函数”(如 list)。之后,每当你访问一个不存在的键时,它会自动调用工厂函数(list())来创建一个空列表作为该键的默认值。
代码实现:
from collections import defaultdict
# 创建时指定,任何新键的默认值都是一个空列表
data = defaultdict(list)
words = ['apple', 'ant', 'ball', 'banana']
for word in words:
key = word[0]
# 直接追加,无需任何检查。defaultdict 在背后处理了一切。
data[key].append(word)
代码的可读性达到了极致,循环体内只剩下最核心的 append 操作。
适用场景: 从头构建一个用于分组或计数的字典时的首选方案。
总结与建议
方法 | 核心思想 | 最佳使用场景 |
---|---|---|
if/else | 手动检查键是否存在 | 简单场景或教学演示 |
setdefault() | 获取键,若不存在则设置默认值 | 对任意普通字典进行操作 |
defaultdict | 访问不存在的键时自动创建默认值 | 从零创建分组/计数专用字典 |
结论:
- 要在普通字典上优雅地追加列表项,请使用 setdefault()。
- 要新建一个分组字典,请选择 defaultdict,它能让你的代码最干净。
掌握这两种方法,能让你的 Python 代码在处理此类常见任务时,显得更加地道和专业。