【问题标题】:Syntax sugar for querying a Python list which element occurs first用于查询 Python 列表中哪个元素首先出现的语法糖
【发布时间】:2012-01-14 18:45:45
【问题描述】:

我有一个包含许多元素的列表。

我关心它的两个元素,ab

我不知道列表的顺序,也不想排序。

如果a 出现在b 之前,是否有一个不错的单行语句返回True,否则返回false?

【问题讨论】:

    标签: python list syntactic-sugar


    【解决方案1】:

    你可以使用list.index:

    l.index(a) < l.index(b)
    

    这当然假设这两个项目都存在于列表中。

    【讨论】:

      【解决方案2】:

      为了多样性,您还可以:

      b in l[l.index(a):]
      

      如果a == b,这将是True。如果你知道a != b

      b in l[l.index(a) + 1:]
      

      【讨论】:

      • 多么蟒蛇!对于 Java 程序员来说,这个含义会完全混淆。我喜欢它!
      • 在我的 Gale-Shapley 实现中,这个例子变成了elif husband[w] in women[w][women[w].index(m):]:ahahah!
      【解决方案3】:

      Mark Byers 的响应效果很好,但如果列表很长并且两个元素都接近结尾,则效率不会很高。

      要遍历列表一次,你可以这样:

      l.index(b, l.index(a))
      

      这是一个需要的单行,但无论如何您都需要捕获ValueError 异常。

      【讨论】:

      • 最快,但是如果我得到一个 ValueError(比如a 发生在b 之后),那么我必须像你说的那样抓住它,增加我的台词!无论如何谢谢你:)
      • 实际上,在 Tim 在上面更新了他的新时代之后,我认为你的答案是最好的答案,尽管必须添加一个 try/except。因此,我将接受的答案更改为您的答案。再次感谢!
      【解决方案4】:

      编辑:重写以检查更多案例

      好的,所以这个问题需要更多的工作。 Mark Byers 完全正确,因为我的第一个测试只涵盖了结果为True 的情况。这一点尤其重要,因为我们需要其他解决方案的异常处理程序。所以我已经更详细地介绍了:

      stmts = {
      "Mark Byers: ": "x = l.index(a) < l.index(b)",
      "jcollado: ": """try:
          x = bool(l.index(b, l.index(a)))
      except ValueError:
          x = False""",
      "Greg Hewgill: ": """try:
         x = b in l[l.index(a):]
      except ValueError:
         x = False"""
      }
      
      setups = ["a = 80; b = 90; l = list(range(100))", 
                "a = 5; b = 10; l = list(range(100))", 
                "a = 90; b = 80; l = list(range(100))",
                "a = 10; b = 5; l = list(range(100))"]
      
      import timeit
      for se in setups:
          print(se)
          for st in stmts:
              print(st, timeit.timeit(stmt=stmts[st], setup=se))
          print()
      

      结果:

      a = 80; b = 90; l = list(range(100))
      Mark Byers:  5.760545506106019
      Greg Hewgill:  3.454101240451526     # Tie!
      jcollado:  3.4574156981854536        # Tie!
      
      
      a = 5; b = 10; l = list(range(100))
      Mark Byers:  1.0853995762934794      # Close runner-up!
      Greg Hewgill:  1.7265326426395209
      jcollado:  1.0528704983320782        # Winner!
      
      a = 90; b = 80; l = list(range(100))
      Mark Byers:  5.741535600372806
      Greg Hewgill:  3.623253643486848     # Winner!
      jcollado:  4.567104188774817
      
      a = 10; b = 5; l = list(range(100))
      Mark Byers:  1.0592141197866987      # Winner!
      Greg Hewgill:  4.73399648151641
      jcollado:  4.77415749512712
      

      因此,jcollado 方法的效率增益大部分被异常处理程序的成本所消耗(特别是如果它触发)。所有三种解决方案都有一半的时间获胜(或与获胜者并列),因此很难说哪种方法最适合您的实际数据。也许您可能想选择最容易阅读的那个。

      【讨论】:

      • 我不知道 timeit 模块。我喜欢 StackOverflow!
      • 谢谢,我想我在使用l[l.index(n):] 方法时没有考虑创建另一个列表对象所需的时间。
      • @jcollado:大概就是这样。恭喜您找到了比两个拥有 > 300k 声望的对手更有效的答案! :)
      • 你所有的测试只测试结果为True的情况。如果答案是False 怎么办?您测试了a = 5, b = 10,但也请尝试a = 10, b = 5,只是为了让它成为一个公平的测试。
      • @MarkByers:很好,在这样做之后,我会更喜欢你的版本,因为在所有情况下都具有更好的可读性和可比的性能。
      猜你喜欢
      • 2018-04-02
      • 1970-01-01
      • 2019-07-10
      • 1970-01-01
      • 1970-01-01
      • 2022-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多