[英]Comparing element order in Python lists
I am trying to write a function that returns True
if the elements in lst1
appear in lst2
in the same order as they appear in lst1
, but not necessarily consecutively. 我正在尝试编写一个函数,如果
lst1
的元素以与它们在lst1
出现的顺序出现在lst2
中,则返回True
,但不一定是连续的。
For example, 例如,
test([29, 5, 100], [20, 29, 30, 50, 5, 100])
should return True
. test([29, 5, 100], [20, 29, 30, 50, 5, 100])
应返回True
。
test([25, 65, 40], [40, 25, 30, 65, 1, 100])
should return False
. test([25, 65, 40], [40, 25, 30, 65, 1, 100])
应返回False
。
Here is what I have so far: 这是我到目前为止:
def test(lst1, lst2):
for i in range(len(lst1)-len(lst2)+1):
if lst2 == lst1[i:i+len(lst2)]:
return True
return False
Here is an iterative version of the method using index
given by Triptych. 这是使用Triptych给出的
index
的方法的迭代版本。 I think this is probably the best way to do this, as index
should be faster than any manual indexing or iteration: 我认为这可能是最好的方法,因为
index
应该比任何手动索引或迭代更快:
def test(lst1, lst2):
start = 0
try:
for item in lst1:
start = lst2.index(item, start) + 1
except ValueError:
return False
return True
It should perform much better in Python than a recursive version. 它在Python中的表现要比递归版本好得多。 It also correctly adds one to the start point after each search so as not to give false positives when there are duplicates in the first list.
它还在每次搜索后正确地向起点添加一个,以便在第一个列表中存在重复时不给出误报。
Here are two solutions that iterate primarily over lst2
instead of lst1
, but are otherwise similar to jedwards' version. 这里有两个主要在
lst2
而不是lst1
上迭代的解决方案,但在其他方面类似于jedwards的版本。
The first is straightforward, and uses indexing, but only indexes when you actually move to a different item in lst1
, rather than for every item in lst2
: 第一个是直截了当的,并使用索引,但只有当你实际移动到
lst1
的不同项而不是lst2
每个项时索引:
def test(lst1, lst2):
length, i, item = len(lst1), 0, lst1[0]
for x in lst2:
if x == item:
i += 1
if i == length:
return True
item = lst1[i]
return False
The second uses manual iteration over lst1
with next
rather than indexing: 第二种是使用手动遍历所有
lst1
与next
,而不是索引:
def test(lst1, lst2):
it = iter(lst1)
try:
i = next(it)
for x in lst2:
if x == i:
i = next(it)
except StopIteration:
return True
return False
Both are probably slight improvements as they do less indexing and have no need to construct a range
for every item in lst1
. 两者都可能略有改进,因为它们的索引较少,并且不需要为
lst1
每个项构建range
。
Recursively, no clobbered lists, no new sublists, failing early 递归地,没有破坏列表,没有新的子列表,提前失败
def find_all(needle, haystack, npos=0, hpos=0):
if npos >= len(needle):
return True
try:
return find_all(needle, haystack, npos+1, haystack.index(needle[npos], hpos)+1)
except ValueError:
return False
print find_all([1,3,5], [1,2,3,4,5,6,7]) # True
print find_all([1,5,3], [1,2,3,4,5,6,7]) # False
This scans the lists and is a different approach: 这会扫描列表,这是一种不同的方法:
def test(lst1, lst2):
p2 = 0
length = len(lst2)
for e1 in lst1:
for p in range(p2, length):
if e1 == lst2[p]:
p2 = p
break
else:
return False
return True
For each element in lst1
it searches the subset of list 2 (between p2
and the end) for it. 对于
lst1
每个元素,它搜索列表2的子集(在p2
和结束之间)。 If it is found, it restricts the range following searches by updating p2
. 如果找到,则通过更新
p2
限制搜索后的范围。 If it is not found, False
is returned. 如果未找到,则返回
False
。 True
is returned if every element in lst1
is found. 如果找到
lst1
每个元素,则返回True
。
def test(lst1, lst2):
for x in lst2:
if x == lst1[0]:
del lst1[0]
return lst1 == []
Should work. 应该管用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.