我有一个从SQLAlchemy Query
返回的对象列表projects =
[
{'project_id': 1, 'project_name': 'A'},
{'project_id': 2, 'project_name': 'B'},
{'project_id': 3, 'project_name': 'C'},
{'project_id': 4, 'project_name': 'D'},
{'project_id': 5, 'project_name': 'E'},
{'project_id': 6, 'project_name': 'F'}
]
我想确保对象列表在此列表中具有项目名称:
project_list = ['A', 'B', 'C']
如果它只是一个值,我可以使用
any(p.project_name == "A" for p in projects)
如何与List进行类似的比较?类似的东西:
any(p.project_name in project_list for p in projects)
上面的代码有效,但我怀疑只要有一个匹配,any()
就会返回True
。
现在,我将对象属性提取到一个新列表中,将两个列表转换为集合并进行比较。
project_names = [project.project_name for project in projects]
assert set(project_list) <= set(project_names)
这样可行,但对于复杂的对象和长列表来说效率很低。
答案 0 :(得分:2)
通过set
进行此操作的方式很好,并且比任何嵌套循环方法都要好得多。为什么你认为它效率低下?
次要优化是直接通过生成器表达式创建项目集,而不是提取临时列表:
project_set = set(p.project_name for p in projects)
然后使用all
而不是project_list
:
assert all(p in project_set for p in project_list)
答案 1 :(得分:1)
您可以使用all
:
all(any(p_name==p.project_name for p in projects) for p_name in projects_list)
或更具可读性:
appears = lambda p_name: any(p_name==p.project_name for p in projects)
all(appears(p_name) for p_name in projects_list)
答案 2 :(得分:0)
如果您确实需要短路行为:遍历对象列表;每当你找到一个你关心的一个添加到一个集合;一旦该集合完整返回True
;否则返回False
。
def f(projects, project_list):
project_list = set(project_list)
seen = set()
for p in projects:
if p.project_name in project_list:
seen.update(p.project_name)
if seen == project_list:
return True
return False
对不起,没有简洁的单行。
答案 3 :(得分:0)
您可能喜欢以下内容
'Project name' in [p.project_name for p in projects]