忽略最后元素时,检查子列表是否存在于列表的最优方法
更高效的列表匹配方案
需求说明
我有如下结构的列表:
[ [1, 2, 'A'], [3, 4, 'B'], [5, 6, 'C'], ... ]
需要检查该列表中是否存在某个子列表,其前两个元素为指定数字m和n,忽略最后一个字符串元素。
我已经实现了最直接的版本:
def contains_first_two(m : int, n : int, search : list) -> bool: for el in search: if el[0] == m and el[1] == n: return True return False
现在想知道有没有更高效的解决方案。
优化方案
1. 预处理为集合(适合多次查询)
如果需要多次执行查询操作,提前把所有子列表的前两个元素转换成元组存入集合,后续查询只需要O(1)时间复杂度:
# 预处理一次 preprocessed = {(el[0], el[1]) for el in search_list} # 查询时直接判断 def contains_first_two(m: int, n: int) -> bool: return (m, n) in preprocessed
这种方式的优势在于,预处理只做一次,之后每次查询都极快,适合频繁查询的场景。
2. 使用生成器表达式简化代码(单次查询效率接近原实现)
如果只是单次查询,可以用生成器表达式替代显式循环,代码更简洁,效率和原实现几乎一致(底层都是迭代遍历):
def contains_first_two(m: int, n: int, search: list) -> bool: return any(el[0] == m and el[1] == n for el in search)
any()函数会在找到第一个匹配项时立即返回,和原实现的提前终止逻辑一致,但代码更紧凑。
3. 提前切片(可读性优化,无效率提升)
如果想让逻辑更清晰,可以提前取出子列表的前两个元素,但不会提升效率,只是代码可读性稍好:
def contains_first_two(m: int, n: int, search: list) -> bool: return any(el[:2] == [m, n] for el in search)
不过切片操作会创建新的列表,相比直接索引el[0]和el[1],反而会有微小的性能损耗,所以更适合追求代码可读性的场景。
方案选择建议
- 频繁查询:选预处理集合的方案,把O(N)的查询成本降到O(1)
- 单次/少量查询:用**生成器表达式+any()**的版本,代码简洁且效率和原实现相当
- 优先可读性:可以用切片的写法,但要注意微小的性能损失
内容的提问来源于stack exchange,提问作者M1n3c4rt
相关产品推荐
相关产品推荐

