Cpt*_*rkt 2 python foreach loops compare list
我有一个名为"UserDatabaseRecord"的类.它有一堆字段,如"username","expiration_date"等.
我有两个UserDatabaseRecord对象列表:列表A和列表B.
我想验证对于列表A中的所有UserDatabaseRecords,用户名字段与列表B中的任何UserDatabaseRecords用户名字段都不匹配.
我能够非常低效地完成这个任务:
for record_a in List_A:
for record_b in List_B:
if record_a.username == record_b.username:
print "Duplicate username: {0}".format(record_a.username)
Run Code Online (Sandbox Code Playgroud)
我觉得它很有用.我只想让它更高效和/或"Pythonic".
这个问题是相关的,但最终我无法弄清楚如何只在一个字段上进行比较时如何将它应用于对象列表:单行检查是否列表中至少有一个项目存在于另一个列表中?
aba*_*ert 10
这个问题是,对于列表A中的每个元素,你要检查列表B中的所有元素.因此,如果列表的长度是N和M,那就是N*M比较.
如果你从列表B中创建一组用户名,那么你可以in在它上面使用运算符 - 这不仅更简单,而且是瞬时的,而不是必须逐个检查所有值.因此,您只需要N次查找而不是N*M.
所以:
b_names = {record.username for record in List_B}
for record_a in List_A:
if record_a.username in b_names:
print "Duplicate username: {0}".format(record_a.username)
Run Code Online (Sandbox Code Playgroud)
或者,甚至更简单,使用集合交集:
a_names = {record.username for record in List_A}
b_names = {record.username for record in List_B}
for name in a_names & b_names:
print "Duplicate username: {0}".format(name)
Run Code Online (Sandbox Code Playgroud)
实际上,你不需要它们都是集合,你可以使用生成器表达式创建一个集合而另一个只是一个迭代器:
a_names = {record.username for record in List_A}
b_names = (record.username for record in List_B)
for name in a_names.intersection(b_names):
print "Duplicate username: {0}".format(name)
Run Code Online (Sandbox Code Playgroud)
其中一个可能比其他一个快一点,但它们都在同一个球场 - 更重要的是,它们都是线性的而不是二次的.所以,我建议使用对你来说最有意义的一个.
如果您只需要知道是否有重复而不是获取它们的列表,或者只需要任意获取其中一个副本而不是所有副本,您可以通过提前"短路"来加速它 - 例如,添加a break在print第一个之后,或者使用isdisjoint而不是intersection在最后一个中.