如何将键为电影、值为演员列表的字典反转为键为演员、值为电影列表的字典

8次阅读

如何将键为电影、值为演员列表的字典反转为键为演员、值为电影列表的字典

本文详解如何将原始字典(电影→[演员列表])高效反转为演员索引字典(演员→[电影列表]),并处理真实数据中常见的换行断裂问题,最终实现按演员名快速查询参演影片的功能。

在影视数据处理中,常需从“电影→演员”映射切换为“演员→电影”索引,以支持按人查片等交互需求。原始代码构建的是 movie_dictionary = {“La La Land”: [“Ryan Gosling”, “Emma Stone”], …},但用户需要输入演员名(如 “Harrison Ford”)后,直接获取其所有参演影片。这本质上是 字典的键值反转,但由于值为列表且存在一对多关系,不能简单使用 {v: k for k, v in d.items()} —— 必须将每个演员作为新键,将其出现的所有电影逐个追加到对应列表中。

✅ 正确的反转逻辑:遍历 + setdefault()

核心思路是:对每一行数据,先分离出电影名和演员列表;再对每位演员(需 .strip() 清理空格),使用 dict.setdefault(key, []) 确保该演员键存在且值为列表,然后 .append(movie):

# 示例:模拟读取文件后的数据行 rows = ["La La Land, Ryan Gosling, Emma Stone",     "Blade Runner 2049, Harrison Ford, Ryan Gosling, Ana de Armas",     # …… 其他行(已确保格式完整)]  appears_in = {}  # 反转后的字典:演员 → [电影列表] for row in rows:     parts = row.split(',')     movie = parts[0].strip()     actors = [a.strip() for a in parts[1:]]  # 清理每位演员首尾空格     for actor in actors:         appears_in.setdefault(actor, []).append(movie)

✅ setdefault() 是关键:若 actor 键不存在,则初始化为空列表 [] 并返回该列表;若已存在,则直接返回原列表。后续 .append(movie) 安全追加,避免 KeyError 或重复初始化。

⚠️ 真实数据陷阱:换行导致的字段断裂

观察原始 movies and actors.txt,部分行末尾有换行符中断(如 “My Best Friend’s Wedding, Julia Roberts, dermont Multroney, nCameron Diaz”),导致 split(‘,’) 后出现孤立的 ” Cameron Diaz” 作为独立行,破坏结构。

修复策略:合并被截断的行
遍历每行,若某行 split(‘,’) 后仅得 1 段(即无逗号),说明它是上一行的延续,应拼接到前一行末尾:

def fix_broken_lines(raw_lines):     fixed = []     buffer = ""for line in raw_lines:         line = line.strip()         if not line:             continue         parts = line.split(',')         if len(parts) == 1 and buffer:  # 孤立片段,追加到缓冲区             buffer +=", "+ line         else:             if buffer:                 fixed.append(buffer)             buffer = line     if buffer:         fixed.append(buffer)     return fixed  # 使用示例 with open("movie and actors.txt","r") as f:     raw_rows = f.readlines() fixed_rows = fix_broken_lines(raw_rows)

? 完整可运行程序(含错误处理)

def build_actor_movie_index(filename):     """从文件构建演员→电影列表字典,自动修复换行断裂"""     with open(filename, "r", encoding="utf-8") as f:         lines = f.readlines()      # 步骤 1:修复断裂行     rows = []     buffer = ""for line in lines:         stripped = line.strip()         if not stripped:             continue         if","not in stripped and buffer:  # 无逗号且有前置内容 → 属于上一行             buffer +=" "+ stripped         else:             if buffer:                 rows.append(buffer)             buffer = stripped     if buffer:         rows.append(buffer)      # 步骤 2:构建反转字典     appears_in = {}     for row in rows:         parts = row.split(',')         if len(parts) <2:             continue  # 跳过无效行         movie = parts[0].strip()         actors = [a.strip() for a in parts[1:] if a.strip()]         for actor in actors:             appears_in.setdefault(actor, []).append(movie)      return appears_in  # 主程序 if __name__ =="__main__":     try:         index = build_actor_movie_index("movie and actors.txt")         name = input("Enter an actor/actress name: ").strip()          if name in index:             movies = index[name]             print(f"The movies that '{name}' starred in are: {','.join(movies)}")         else:             print(f"No movies found for '{name}'. Check spelling or try another name.")      except FileNotFoundError:         print("Error: File 'movie and actors.txt' not found.")     except Exception as e:         print(f"An error occurred: {e}")

? 关键总结

  • 不要用 dict(zip(values, keys)):因原值是列表,会丢失多对一关系;
  • 优先用 setdefault():比手动 if key not in d: d[key] = [] 更简洁安全;
  • 务必清洗数据:.strip() 处理空格,预处理修复换行断裂;
  • 增强健壮性:加入 try/except 和空行 / 无效行过滤;
  • 用户体验优化:提示拼写检查,避免 KeyError 导致程序崩溃。

通过以上方法,你不仅能正确反转字典结构,还能应对真实数据中的典型噪声,构建出可靠、可维护的影视索引系统。

text=ZqhQzanResources