查询Python列表中哪个元素先出现的语法糖
我有一个包含很多元素的列表。
我只关心其中的两个元素,a
和b
。
我不知道这个列表的顺序,也不想去排序它。
有没有一种简单的方法,可以在一行代码里判断,如果a
出现在b
之前,就返回True
,否则返回False
?
4 个回答
7
你可以使用 list.index
这个方法:
l.index(a) < l.index(b)
当然,这个方法是建立在列表中同时存在这两个项目的基础上的。
9
为了增加多样性,你还可以这样做:
b in l[l.index(a):]
如果 a
和 b
相等,这个结果会是 True
。如果你知道 a
和 b
不相等,
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 的方法在效率上的提升大部分被异常处理的成本抵消了(尤其是当异常被触发时)。这三种解决方案在一半的情况下都能获胜(或者与获胜者平局),所以到底哪种方法在你的实际数据上效果最好,真的很难说。也许你可以选择那种最容易理解的方法。