字典生成 去年帮朋友处理一批用户数据,字典生成三万条记录,字典生成字段包括姓名、字典生成手机号、字典生成注册时间、字典生成消费金额。字典生成他想按城市分组统计消费总额。字典生成我打开Python,字典生成写了不到十行代码就搞定了。字典生成核心就一个东西——字典。字典生成 字典这玩意儿,字典生成说白了就是字典生成键值对的集合。你给它一个键,字典生成它还你一个值。字典生成跟查字典一模一样,字典生成翻到"apple",看到"苹果",完事。Python里用花括号{ }表示,键和值之间用冒号隔开,不同对之间用逗号分开。就这么简单。 city_stats = { } for record in data: city = record['city'] amount = record['amount'] if city in city_stats: city_stats[city] += amount else: city_stats[city] = amount 这段代码干了什么?遍历每条记录,看城市在不在字典里。在,就累加金额;不在,就新建一个键,把金额存进去。跑完三万条数据,不到0.1秒。要是用列表去查,每次都得遍历一遍,那速度能让你等到怀疑人生。 字典生成这词儿有两层意思。一层是动态构建——像上面那样,边遍历边往字典里塞东西。另一层是字典推导式,Python里叫dict comprehension。这玩意儿写起来更紧凑。 city_stats = { } for record in data: city = record['city'] city_stats[city] = city_stats.get(city, 0) + record['amount'] 用get方法省掉了if-else。get(city, 0)的意思是:如果city这个键存在,返回它的值;不存在,返回0。然后加金额,再赋回去。一行搞定,干净利落。 但字典推导式更狠。比如你要把两个列表拼成字典: keys = ['name', 'age', 'city'] values = ['Alice', 28, 'Beijing'] person = { k: v for k, v in zip(keys, values)} 结果就是{ 'name': 'Alice', 'age': 28, 'city': 'Beijing'}。zip把两个列表配对,推导式再把它们塞进字典。这种写法在数据清洗时特别顺手。比如你有一堆用户ID和对应的邮箱,想快速建个映射表,一行就够了。 不过字典有个坑:键必须是不可变的。字符串、数字、元组都行,列表不行。因为字典内部用哈希表实现,键的哈希值不能变。你拿列表当键,Python直接甩你一个TypeError。我当初就被这个坑过,调了半天才发现问题出在键的类型上。 另一个常见操作是嵌套字典。比如按城市分组后,还想按月份细分: stats = { } for record in data: city = record['city'] month = record['month'] if city not in stats: stats[city] = { } if month not in stats[city]: stats[city][month] = 0 stats[city][month] += record['amount'] 这样stats['Beijing']['2024-01']就能直接拿到北京一月份的消费总额。嵌套层数别太多,超过三层就该考虑用类或者数据库了。字典虽然灵活,但嵌套太深,代码可读性直线下降。 实际工作中,字典生成往往跟数据聚合绑在一起。Pandas的groupby底层也在干类似的事,只是封装得更高级。但理解字典的构建过程,能帮你判断什么时候该用groupby,什么时候手写循环更划算。数据量小的时候,手写字典反而更快,因为省掉了Pandas的初始化开销。 最后说个实用技巧:collections模块里的defaultdict。它自动处理键不存在的情况,省掉一堆if判断。 from collections import defaultdict city_stats = defaultdict(float) for record in data: city_stats[record['city']] += record['amount'] defaultdict(float)的意思是:访问不存在的键时,自动创建一个默认值0.0。代码又短了一截。类似的还有Counter,专门用来计数。这些工具用熟了,写数据处理的代码就跟搭积木一样。 字典生成不是啥高深技术,但它是数据处理的基石。你把它玩转了,很多看似复杂的问题,拆开来看不过是几个键值对的事。 |