我知道如何查找列表是否是另一个列表的子集。但我想知道如何确保列表是另一个列表的有序子集。按顺序子集,我的意思是列表中的元素顺序相同
例如,如果我有以下列表
A = [1,2,3]
B = [1,2]
C = [2,1]
这里B是A的有序子集,但C不是(尽管A具有C的所有元素)
答案 0 :(得分:3)
使用简单的循环按顺序遍历两个列表。最后,检查是否已经看到潜在子集列表的所有元素。
i,j = 0,0
while i < len(A) and j < len(B):
if A[i] == B[j]:
j += 1
i += 1
has_as_subset = (j == len(B))
答案 1 :(得分:1)
def is_sub(sub, lst):
ln = len(sub)
for i in range(len(lst) - ln + 1):
if all(sub[j] == lst[i+j] for j in range(ln)):
return True
return False
输出:
In [21]: A = [4, 3, 2, 1, 2, 3]
In [22]: B = [1, 2]
In [23]: C = [2, 1]
In [24]: is_sub(B, A)
Out[24]: True
In [25]: is_sub(C, A)
Out[25]: True
In [26]: B = [10,11,12,13,14,15,25]
In [27]: is_sub(B, A)
Out[27]: False
In [39]: A = [1, 2, 1, 2, 1, 2, 3]
In [40]: B = [1, 2, 3]
In [41]: is_sub(B, A)
Out[41]: True
我们不需要担心sub比lst更长,因为它停止的时间会少于start,所以我们只返回False。
您可以将它与任何:
结合使用def is_sub(s, l):
ln = len(s)
return any((all(s[j] == l[i + j] for j in range(ln))
for i in range(len(l) - ln + 1)))
根据您的使用情况,切片可能会更快:
def is_sub(sub, lst):
ln = len(sub)
return any(lst[i: i + ln] == sub for i in range(len(sub) - ln + 1))
如果元素可以有间隙,那么它就会简单得多,类似于kfx,你可以在一次通过或更少的时间内完成:
def is_sub_with_gap(sub, lst):
ln, j = len(sub), 0
for ele in lst:
if ele == sub[j]:
j += 1
if j == ln:
return True
return False
根本区别在于你认为是一个子集:
In [6]: a,b = [1,2,3,4], [1,2,4]
In [7]: is_sub(b,a)
Out[7]: False
In [8]: is_sub_with_gap(b,a)
Out[8]: True
答案 2 :(得分:0)
a_i = 0
for b in B:
try:
if b == A[a_i]:
a_i += 1
except IndexError:
return False
return True
基本的想法是,在耗尽A
之前,你不应该耗尽B
。
答案 3 :(得分:0)
这是一个允许与大多数共同但不是所有其他已发布解决方案的差距(即is_sublist([1,2,4],[1,2,3,4])
返回True
)的版本;它还处理从父列表中的任何位置开始的子列表(同样,与大多数但不是所有其他答案一样);此外,如果子列表候选包含主列表没有的重复(即False
不是[1,2,2]
的子列表),则返回[1,2,3]
:同样,此属性是共享的大多数但不是所有其他答案。 (据我所知,唯一能够击中所有这些目标的解决方案是kfx。)
def is_sublist( sublst, lst ):
for element in sublst:
try: ind = lst.index( element )
except ValueError: return False
lst = lst[ ind+1: ]
return True