【问题标题】:Python 2.6: How can I compare two lists of same object types on one particular field, efficiently?Python 2.6:如何有效地比较一个特定字段上相同对象类型的两个列表?
【发布时间】:2014-02-16 04:59:19
【问题描述】:

我有一个名为“UserDatabaseRecord”的类。它有一堆字段,如“用户名”、“到期日期”等。

我有两个 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)

我猜它有效。我只是想让它更高效和/或“Pythonic”。

这个问题是相关的,但最终我无法弄清楚如何将其应用于 objects 列表,仅在一个字段上进行比较:one-liner to check if at least one item in list exists in another list?

【问题讨论】:

  • 是否有理由让您的班级 list 支持而不是 dict 支持?如果它是由用户名键入的,则此操作是即时的,并且是一行。
  • @roippi 不,你说得很好。除了在项目开始时我对 Lists 更加熟悉和熟悉之外,我没有什么特别的原因。这是一个小项目,所以没什么大不了的,但肯定会在我未来的项目中更好地利用。
  • @CptSupermrkt:在这个项目中重新排列您的数据可能仍然值得。毕竟,如果是一个小项目,应该是一个简单的改变,一个很好的学习体验,对吧?

标签: python list loops foreach compare


【解决方案1】:

你可以试试这样的:

for rec_a, rec_b in zip(List_A, List_B):
    if rec_a == rec_b:
        print "Duplicate username: {0}".format(rec_a.username)

【讨论】:

  • 这完全不同;它只检查List_B 中的每个元素与List_A 中的相应元素;他想检查List_A中的所有元素。
【解决方案2】:

这样做的问题是,对于列表 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)

或者,更简单,使用集合交集:

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)

实际上,您不需要将它们都设为集合,您可以使用生成器表达式将一个设为集合,而将另一个设为迭代器:

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)

其中一个可能比其他的快一点,但它们都在同一个范围内——更重要的是,它们都是线性的,而不是二次的。所以,我建议使用对您最有意义的一个。

如果您只需要知道是否有重复项而不是获取它们的列表,或者只需要任意获取其中一个重复项而不是所有重复项,您可以通过尽早“短路”来加快速度——例如,在第一个print 之后添加break,或者在最后一个中使用isdisjoint 而不是intersection

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    • 2019-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-23
    相关资源
    最近更新 更多