在真实业务里,数据常以字典嵌套列表的形式出现,例如用户标签、订单商品等。我们常常需要统计这些嵌套列表里的值,在另一个目标列表中总共出现了多少次。下面介绍几种高效且易读的Python实现方式。
一、问题示例
假设有如下字典,其值均为列表,同时有一个目标列表,我们要统计字典中所有列表元素在目标列表中的出现次数:
data = {
'a': ['apple', 'banana', 'pear'],
'b': ['banana', 'orange'],
'c': ['apple', 'grape']
}
target = ['apple', 'banana', 'apple', 'peach']
# 期望统计 data 中每个出现在 target 里的元素次数总和
# apple 出现 2 次(data中),banana 出现 2 次(data中),都应在 target 中计数
二、使用生成器与 Counter
最直观且高效的做法是先用生成器表达式展开所有嵌套值,再用 collections.Counter 结合目标列表统计:
from collections import Counter
data = {
'a': ['apple', 'banana', 'pear'],
'b': ['banana', 'orange'],
'c': ['apple', 'grape']
}
target = ['apple', 'banana', 'apple', 'peach']
# 展开字典中的所有列表值
all_values = (item for lst in data.values() for item in lst)
# 统计 target 中每个元素的出现次数
target_counter = Counter(target)
# 计算嵌套列表值在目标列表中的总出现次数
result = sum(count * target_counter.get(value, 0) for value, count in Counter(all_values).items())
print(result) # 输出 4
代码说明
- Counter(all_values) 统计字典嵌套列表中各值出现次数
- target_counter.get(value, 0) 获取该值在目标列表中的频次
- sum 将两者相乘后累加,得到高效统计结果
三、仅统计存在性
如果只关心嵌套值是否在目标列表中出现过,而不关心目标列表自身频次,可用集合提升性能:
data = {
'a': ['apple', 'banana', 'pear'],
'b': ['banana', 'orange'],
'c': ['apple', 'grape']
}
target_set = {'apple', 'banana', 'apple', 'peach'}
nested_set = {item for lst in data.values() for item in lst}
hit_count = len(nested_set & target_set)
print(hit_count) # 输出 2,即 apple 和 banana 命中
四、性能对比建议
| 方法 | 适用场景 | 时间复杂度 |
|---|---|---|
| Counter 相乘 | 需按目标频次加权 | O(N+M) |
| 集合交集 | 仅看是否包含 | O(N+M) |
| 多重 for 循环 | 逻辑最直白 | O(N*M) |
对于大数据量,应优先使用 Counter 或集合,避免写多层 for 循环导致代码冗长且缓慢。
小结:字典嵌套列表的统计核心是先扁平化再匹配,善用标准库能让代码既高效又清晰。