如何用列表推导式从字典列表中移除指定start/end值的元素?
问题解决:从字典列表中移除指定start/end匹配的元素
问题需求
现有待删除的起止元组列表:
items_to_delete = [(69, 70), (84, 88)]
需要从下面的字典列表中,移除所有start和end值与上述元组完全匹配的元素:
input_list = [ {'name': 'John', 'gender': 'male', 'start': 69, 'end': 70}, {'name': 'Sara', 'gender': 'female', 'start': 75, 'end': 80}, {'name': 'George', 'gender': 'male', 'start': 84, 'end': 88}, {'name': 'James', 'gender': 'male', 'start': 98, 'end': 101} ]
预期输出:
[{'name': 'Sara', 'gender': 'female', 'start': 75, 'end': 80}, {'name': 'James', 'gender': 'male', 'start': 98, 'end': 101}]
原代码问题分析
你写的列表推导式用了两层for循环,逻辑上有问题:每个字典会和items_to_delete里的每个元组逐一比对,只要某次比对符合not (start和end匹配)的条件,就会把这个字典加入结果列表。比如Sara的字典,和(69,70)比对时符合保留条件,和(84,88)比对时也符合,结果会被重复添加,最终输出的元素数量会超出预期,完全不对。
正确实现方法
方法1:用all()确保完全不匹配
通过all()函数判断当前字典的(start,end)和所有删除项都不匹配,才保留该字典:
items_to_delete = [(69, 70), (84, 88)] input_list = [ {'name': 'John', 'gender': 'male', 'start': 69, 'end': 70}, {'name': 'Sara', 'gender': 'female', 'start': 75, 'end': 80}, {'name': 'George', 'gender': 'male', 'start': 84, 'end': 88}, {'name': 'James', 'gender': 'male', 'start': 98, 'end': 101} ] res = [dict_ent for dict_ent in input_list if all(not (dict_ent['start'] == item[0] and dict_ent['end'] == item[1]) for item in items_to_delete)] print(res)
方法2:转集合优化查找(更高效)
因为元组是可哈希类型,把items_to_delete转成集合后,in操作的时间复杂度是O(1),数据量大时效率更高,逻辑也更直观:
# 直接定义为集合,或者用set(items_to_delete)转换原列表 items_to_delete = {(69, 70), (84, 88)} input_list = [ {'name': 'John', 'gender': 'male', 'start': 69, 'end': 70}, {'name': 'Sara', 'gender': 'female', 'start': 75, 'end': 80}, {'name': 'George', 'gender': 'male', 'start': 84, 'end': 88}, {'name': 'James', 'gender': 'male', 'start': 98, 'end': 101} ] res = [dict_ent for dict_ent in input_list if (dict_ent['start'], dict_ent['end']) not in items_to_delete] print(res)
这两种方法都能得到符合预期的输出,其中方法2更简洁高效,推荐优先使用。
内容的提问来源于stack exchange,提问作者Jenny Distel
相关产品推荐
相关产品推荐

