如何以Pythonic方式从两个列表生成指定结构的字典?
更Pythonic的实现方案
首先得指出原实现的两个小问题:一是当l2开头的元素不在l1中时,结果里会多出一个空字符串键(这不符合需求);二是x in l1的查找效率是O(n),当l1元素较多时会拖慢性能。
咱们可以用更清晰、高效的方式来实现需求,核心思路是先定位l2中所有属于l1的元素的位置,再通过切片提取相邻键之间的元素,同时用集合优化查找效率。
方案一:兼容所有Python版本
l1 = ['a', 'c', 'b', 'e', 'f', 'd'] l2 = ['x','q','we','da','po', 'a', 'el1', 'el2', 'el3', 'el4', 'b', 'some_other_el_1', 'some_other_el_2', 'c', 'another_element_1', 'another_element_2', 'd', '', '', 'another_element_3', 'd4'] # 转成集合,把查找操作从O(n)优化为O(1) l1_set = set(l1) # 收集l2中属于l1的元素及其索引 key_positions = [] for idx, elem in enumerate(l2): if elem in l1_set: key_positions.append((idx, elem)) result = {} # 遍历每个键,提取对应的元素列表 for i in range(len(key_positions)): curr_idx, curr_key = key_positions[i] # 确定当前键对应的元素区间的结束索引 if i < len(key_positions) - 1: next_idx = key_positions[i+1][0] else: next_idx = len(l2) # 切片获取相邻键之间的元素 result[curr_key] = l2[curr_idx + 1 : next_idx] print(result)
方案二:Python 3.10+ 更简洁版本
利用itertools.pairwise来简化相邻位置的遍历,代码更紧凑:
from itertools import pairwise l1 = ['a', 'c', 'b', 'e', 'f', 'd'] l2 = ['x','q','we','da','po', 'a', 'el1', 'el2', 'el3', 'el4', 'b', 'some_other_el_1', 'some_other_el_2', 'c', 'another_element_1', 'another_element_2', 'd', '', '', 'another_element_3', 'd4'] l1_set = set(l1) key_positions = [(idx, elem) for idx, elem in enumerate(l2) if elem in l1_set] # 添加一个哨兵位置,处理最后一个键到l2末尾的元素 key_positions.append((len(l2), None)) result = {} for (curr_idx, curr_key), (next_idx, _) in pairwise(key_positions): result[curr_key] = l2[curr_idx + 1 : next_idx] print(result)
为什么这两种方式更Pythonic?
- 性能优化:用集合
set(l1)将元素查找的时间复杂度从O(n)降到O(1),尤其适合l1元素较多的场景。 - 逻辑清晰:通过显式定位键的位置,避免了原代码中维护临时键的混乱逻辑,可读性更强。
- 符合需求:不会生成多余的空键,只保留l2中存在于l1的元素作为键。
- 简洁高效:方案二利用标准库工具简化遍历,代码更紧凑且易维护。
内容的提问来源于stack exchange,提问作者Cristian Harangus
相关产品推荐
相关产品推荐

