查询Python列表中哪个元素先出现的语法糖

12 投票
4 回答
613 浏览
提问于 2025-04-17 07:52

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

我只关心其中的两个元素,ab

我不知道这个列表的顺序,也不想去排序它。

有没有一种简单的方法,可以在一行代码里判断,如果a出现在b之前,就返回True,否则返回False

4 个回答

7

你可以使用 list.index 这个方法:

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

当然,这个方法是建立在列表中同时存在这两个项目的基础上的。

9

为了增加多样性,你还可以这样做:

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

如果 ab 相等,这个结果会是 True。如果你知道 ab 不相等,

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

编辑:重写以检查更多情况

好的,这个问题需要再多花点功夫。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 的方法在效率上的提升大部分被异常处理的成本抵消了(尤其是当异常被触发时)。这三种解决方案在一半的情况下都能获胜(或者与获胜者平局),所以到底哪种方法在你的实际数据上效果最好,真的很难说。也许你可以选择那种最容易理解的方法。

撰写回答