我正在尝试编写一个函数,如果True
中的元素以lst1
中出现的顺序出现在lst2
中,则会返回lst1
,但不一定连续。
例如,
test([29, 5, 100], [20, 29, 30, 50, 5, 100])
应该返回True
。
test([25, 65, 40], [40, 25, 30, 65, 1, 100])
应该返回False
。
这是我到目前为止所做的:
def test(lst1, lst2):
for i in range(len(lst1)-len(lst2)+1):
if lst2 == lst1[i:i+len(lst2)]:
return True
return False
答案 0 :(得分:5)
这是使用Triptych提供的index
的方法的迭代版本。我认为这可能是最好的方法,因为index
应该比任何手动索引或迭代更快:
def test(lst1, lst2):
start = 0
try:
for item in lst1:
start = lst2.index(item, start) + 1
except ValueError:
return False
return True
它在Python中的表现要比递归版本好得多。它还在每次搜索后正确地将一个添加到起点,以便在第一个列表中存在重复时不会给出误报。
以下两种解决方案主要在lst2
而不是lst1
上进行迭代,但在其他方面与jedwards的版本相似。
第一个是直截了当的,并且使用索引,但只在您实际移动到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
第二个使用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
两者都可能略有改进,因为它们的索引编制较少,而且无需为range
中的每个项目构建lst1
。
答案 1 :(得分:2)
递归地,没有破坏列表,没有新的子列表,早期失败
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
答案 2 :(得分:1)
这会扫描列表,这是一种不同的方法:
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
对于lst1
中的每个元素,它搜索列表2的子集(在p2
和结束之间)。如果找到,则会通过更新p2
来限制搜索后的范围。如果未找到,则返回False
。如果找到True
中的每个元素,则会返回lst1
。
答案 3 :(得分:0)
def test(lst1, lst2):
for x in lst2:
if x == lst1[0]:
del lst1[0]
return lst1 == []
应该工作。