如何使用生成器函数从嵌套字典中筛选指定用户的rating值
问题说明
现有存储产品信息的嵌套字典列表,需要使用带yield的生成器遍历所有reviews字段对应的评论列表,筛选指定user关联的所有rating值,最终以字典形式返回结果。例:目标用户为A11时,应返回关联的2条评分记录。
原始测试数据结构如下:
data = [{ "product_id" : "123", "size" : "L", "color" : "blue", "reviews" : [ { "user" : "A11", "rating" : "score1" }, { "user" : "Z99", "rating" : "score" }] }, { "product_id" : "987", "size" : "M", "color" : "red", "reviews" : [ { "user" : "A11", "rating" : "score2" }, { "user" : "X55", "rating" : "score" }] } ]
原有生成器代码的问题:
代码采用递归遍历所有嵌套结构,只要找到键名和传入参数匹配的字段就直接返回值,没有加入user字段的匹配判断逻辑,因此会返回所有层级下的全部rating值,无法实现指定用户的筛选。原有错误代码如下:
def user_rating(nest, kv): if isinstance(nest, list): for i in nest: for x in user_rating(i, kv): yield x elif isinstance(nest, dict): if kv in nest: yield nest[kv] for j in nest.values(): for x in user_rating(j, kv): yield x print(list(user_rating(data, 'rating')))
修改方案
方案1:定向遍历(推荐,结构固定场景使用)
由于数据结构明确,评分数据全部存储在每个产品字典的reviews列表下,每个评论条目是同时包含user、rating键的平级字典,不需要做全量嵌套递归,直接定向遍历即可,逻辑清晰性能更高:
def user_rating(data, target_user): # 遍历外层所有产品条目 for product in data: # 遍历当前产品下的所有评论,reviews不存在时返回空列表避免报错 for review in product.get("reviews", []): # 匹配到目标用户时,返回对应评分字典 if review.get("user") == target_user: yield {"user": target_user, "rating": review.get("rating")} # 测试查询用户A11的所有评分 if __name__ == "__main__": result = list(user_rating(data, "A11")) print(result)
运行输出:
[{'user': 'A11', 'rating': 'score1'}, {'user': 'A11', 'rating': 'score2'}]
方案2:递归遍历(适配嵌套结构变动场景)
如果需要保留递归逻辑,适配未来可能的reviews层级变动,可以在递归判断中增加评论条目识别逻辑:当遍历到的字典同时包含user和rating键时,校验用户是否匹配,匹配成功再返回结果:
def user_rating(nest, target_user): if isinstance(nest, list): for item in nest: yield from user_rating(item, target_user) elif isinstance(nest, dict): # 识别到标准评论条目结构 if "user" in nest and "rating" in nest: if nest["user"] == target_user: yield {"user": target_user, "rating": nest["rating"]} # 继续递归遍历字典下的所有值 for value in nest.values(): yield from user_rating(value, target_user) # 测试效果和方案1完全一致 print(list(user_rating(data, "A11")))
两种方案差异:
- 定向遍历版本:路径明确、运行效率高,适合数据结构长期固定的业务场景
- 递归遍历版本:兼容性更强,只要评论条目本身的
user、rating键结构不变,就算外层嵌套层级调整也不需要修改代码
内容的提问来源于stack exchange,提问作者elideli
相关产品推荐
相关产品推荐

