使用Python在另一个列表中搜索一个列表的值
我正在尝试查找列表的子列表.这意味着如果list1说[1,5]在list2中说[1,4,3,5,6],则它应该返回True.到目前为止,我的情况是这样:
I'm a trying to find a sublist of a list. Meaning if list1 say [1,5] is in list2 say [1,4,3,5,6] than it should return True. What I have so far is this:
for nums in l1:
if nums in l2:
return True
else:
return False
这将是正确的,但我仅在list1以相应顺序位于list2中时才尝试返回True.因此,如果list2为[5,2,3,4,1],则应返回False.我一直在考虑使用<比较list1的索引值的思路.但我不确定.
This would be true but I'm trying to return True only if list1 is in list2 in the respective order. So if list2 is [5,2,3,4,1], it should return False. I was thinking along the lines of comparing the index values of list1 using < but I'm not sure.
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
)的位置;像这里一样,通过第二个arg调用它,它开始在列表中的该位置查找.如果index
找不到所需的内容,则会引发ValueError
异常.
The index
method of list L2 returns the position at which the first argument (num
) is found in the list; called, like here, with a second arg, it starts looking in the list at that position. If index
does not find what it's looking for, it raises a ValueError
exception.
因此,此代码使用此方法在L2
中按顺序查找L1
的每个项目num
.第一次需要从位置0开始寻找;接下来的每次,它都需要从找到上一个项目的最后一个位置之后的位置开始寻找,即last_found + 1
(因此,开始时,我们必须将last_found = -1
设置为第一次从位置0开始寻找).
So, this code uses this approach to look for each item num
of L1
, in order, inside L2
. The first time it needs to start looking from position 0; each following time, it needs to start looking from the position just after the last one where it found the previous item, i.e. last_found + 1
(so at the start we must set last_found = -1
to start looking from position 0 the first time).
如果以这种方式找到了L1中的每个项目(即在找到前一个项目的位置之后在L2中找到了项目),则两个列表均满足给定条件,并且代码返回True
.如果找不到L1的任何项,则代码将捕获产生的ValueError
异常,并仅返回False
.
If every item in L1 is found this way (i.e. it's found in L2 after the position where the previous item was found), then the two lists meet the given condition and the code returns True
. If any item of L1 is ever not-found, the code catches the resulting ValueError
exception and just returns False
.
另一种方法是在两个列表上使用 iterators ,这可以通过iter
内置函数来形成.您可以通过调用内置的next
来高级"迭代器.如果没有下一项",即迭代器用尽,这将引发StopIteration
.如果适用,您还可以在迭代器上使用for
以获得更平滑的界面.使用iter/next想法的低级方法:
A different approach would be to use iterators over the two lists, that can be formed with the iter
built-in function. You can "advance" an iterator by calling built-in next
on it; this will raise StopIteration
if there is no "next item", i.e., the iterator is exhausted. You can also use for
on the iterator for a somewhat smoother interface, where applicable. The low-level approach using the iter/next idea:
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:
,外循环也可能如此,因为它没有重新启动"的问题.
In fact, the only crucial use of iter
here is to get i2 -- having the inner loop as for maybe in i2
guarantees the inner loop won't start looking from the beginning every time, but, rather, it will keep looking where it last left off. The outer loop might as well for for lookfor in L1:
, since it has no "restarting" issue.
键是循环的else:
子句,当且仅当该循环未被break
中断而是自然退出时才触发.
Key, here, is the else:
clause of loops, which triggers if, and only if, the loop was not interrupted by break
but rather exited naturally.
进一步研究这个想法,我们再次想到了in
运算符,只需使用迭代器,也可以使该运算符继续到上一个中断的地方.大大简化:
Working further on this idea we are again reminded of the in
operator, which also can be made to continue where it last left off simply by using an iterator. Big simplification:
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
内置的短路蓄电池"功能所抽象的模式,所以...:
But now we recognize that is exactly the patter abstracted by the short-circuiting any
and all
built-in "short-circuiting accumulator" functions, so...:
i2 = iter(L2)
return all(lookfor in i2 for lookfor in L1)
我相信这几乎就是您所能获得的.这里剩下的唯一非基本元素是:您只需一次使用一次iter(L2)
即可确保in
运算符(本质上是一个内部循环)不会从头开始搜索,而是继续每个搜索从上次停止的时间开始.
which I believe is just about as simple as you can get. The only non-elementary bit left here is: you need to use an iter(L2)
explicitly, just once, to make sure the in
operator (intrinsically an inner loop) doesn't restart the search from the beginning but rather continues each time from where it last left off.