try:
last_found = -1
for num in L1:
last_found = L2.index(num, last_found + 1)
return True
except ValueError:
return False
列表L2的索引方法返回列表中第一个参数(num)的位置;像这里一样,用第二个arg调用,它开始查看该位置的列表.如果索引找不到它要查找的内容,则会引发ValueError异常.
因此,此代码使用此方法在L2内按顺序查找L1的每个项目数.第一次需要从0位开始寻找;每个下一个时间,它需要从它找到前一个项目的最后一个位置之后的位置开始查看,即last_found 1(所以在开始时我们必须设置last_found = -1以便第一次从位置0开始查看).
如果L1中的每个项都以这种方式找到(即它在找到前一项的位置之后的L2中找到),则两个列表满足给定条件并且代码返回True.如果找不到任何L1项,代码将捕获结果ValueError异常并返回False.
另一种方法是在两个列表上使用迭代器,这可以使用iter内置函数形成.你可以通过调用下面的内置函数来“推进”迭代器;如果没有“下一个项目”,这将引发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 – 内部循环可能在i2中保证内部循环不会从头开始每次都看起来,但相反,它会继续寻找它的位置最后离开.外部循环也可以用于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
但是现在我们认识到这正是由短路任何和所有内置的“短路累加器”功能所抽象的模式,所以…:
i2 = iter(L2)
return all(lookfor in i2 for lookfor in L1)
我认为这就像你能得到的一样简单.这里留下的唯一非基本位是:你需要显式地使用iter(L2),只需要一次,以确保in运算符(本质上是一个内部循环)不会从头重新开始搜索,而是每次都继续从它最后离开的地方.