try:
last_found = -1
for num in L1:
last_found = L2.index(num, last_found + 1)
return True
except ValueError:
return False
列表L2的index方法返回第一个参数(num)在列表中的位置;像这里一样,使用第二个参数调用,它开始在该位置查找列表。如果index 没有找到它要查找的内容,则会引发ValueError 异常。
因此,此代码使用此方法在L2 中按顺序查找num 中的每个项目num。第一次需要从位置0开始查找;接下来的每一次,它需要从它找到上一个项目的最后一个位置之后的位置开始查找,即last_found + 1(所以在开始时我们必须设置last_found = -1第一次从位置0开始查找)。
如果以这种方式找到 L1 中的每个项目(即在 L2 中找到上一个项目的位置之后),则两个列表满足给定条件,代码返回 True。如果未找到 L1 的任何项目,代码将捕获生成的 ValueError 异常并仅返回 False。
另一种方法是在两个列表上使用迭代器,这可以通过iter 内置函数形成。您可以通过调用内置的 next 来“推进”迭代器;如果没有“下一项”,这将引发StopIteration,即迭代器已用尽。如果适用,您还可以在迭代器上使用for 以获得更平滑的界面。使用 iter/next 思想的底层方法:
i1 = iter(L1)
i2 = iter(L2)
while True:
try:
lookfor = next(i1)
except StopIteration:
# no more items to look for == all good!
return True
while True:
try:
maybe = next(i2)
except StopIteration:
# item lookfor never matched == nope!
return False
if maybe == lookfor:
break
或者,更高级一点:
i1 = iter(L1)
i2 = iter(L2)
for lookfor in i1:
for maybe in i2:
if maybe == lookfor:
break
else:
# item lookfor never matched == nope!
return False
# no more items to look for == all good!
return True
事实上,iter 的唯一关键用途是获取 i2 —— 将内循环设为 for maybe in i2 保证内循环不会每次都从头开始查找,而是,它会继续寻找上次停止的地方。 for lookfor in L1: 也可以使用外部循环,因为它没有“重启”问题。
这里的关键是循环的else: 子句,当且仅当循环没有被break 中断而是自然退出时才会触发。
进一步研究这个想法,我们再次想起了in 运算符,它也可以通过使用迭代器从上次中断的地方继续。大简化:
i2 = iter(L2)
for lookfor in L1:
if lookfor not in i2:
return False
# no more items to look for == all good!
return True
但现在我们认识到这正是短路 any 和 all 内置“短路累加器”函数所抽象的模式,所以...:
i2 = iter(L2)
return all(lookfor in i2 for lookfor in L1)
我相信这和你能得到的一样简单。这里剩下的唯一非基本位是:您需要明确地使用 iter(L2) 一次,以确保 in 运算符(本质上是一个内部循环)不会从头开始重新开始搜索,而是继续每个上次停止的时间。