[英]Python: any() to check if attribute in List of Objects matches a list
我有一個從SQLAlchemy查詢返回的對象的列表
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)
如何與列表進行類似比較? 就像是:
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)
這是可行的,但對於復雜的對象和較長的列表將效率不高。
通過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)
您可以使用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)
如果您確實需要短路行為:遍歷對象列表; 每次找到一個,您就關心將其添加到集合中; 一旦設置滿則返回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
抱歉,沒有那么臟。
您可能喜歡以下內容
'Project name' in [p.project_name for p in projects]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.