[英]How to check if a list (string) contains another list (string) considering order
我有两个列表(或字符串):一个很大,另一个很小。 我想检查较大的(A)是否包含较小的(B)。
我的期望如下:
案例 1. B 是 A 的子集
A = [1,2,3]
B = [1,2]
contains(A, B) = True
情况2.B不是A的子集,但在A中维护了[1,2]的顺序
A = [1,3,2]
B = [1,2]
contains(A, B) = True
案例 3. 错误,因为 4 in not A
A = [1,3,2]
B = [1,4]
contains(A, B) = False
案例 4. 错误,因为 A 中没有维护顺序 [2,1],即使 A 包含 1 和 2。
A = [1,3,2]
B = [2,1]
contains(A, B) = False
A 和 B 可以是字符串。
我很确定检查一个列表是否是另一个列表的子列表是一种经典的贪心算法。 我们可以扫描较大的列表,尝试按顺序查找较小列表中的每个项目。 我们永远不需要回溯,因为每个元素的第一次出现都很好。
def contains(larger, smaller):
# Take an iterator so that we always pick up where we left off.
larger_iter = iter(larger)
for s in smaller:
for l in larger_iter:
if s == l:
break
else:
# We'll enter the else block if we *didn't* break in the loop,
# in which case we never found a match for s.
return False
return True
这将在较大列表的大小上线性运行,因为我们最多迭代一次。
编辑。 昨晚我想知道是否有一个更小的(逐行)解决方案仍然是线性的,我现在有一个我喜欢的解决方案。
def contains(larger, smaller):
larger_iter = iter(larger)
return all(s in larger_iter for s in smaller)
这遵循与上述完全相同的算法,只是使用更高级别的 function 来处理一些簿记。 s in larger_iter
对应带有 else 块的内部 for 循环,带有 generator 的all
对应外部 for 循环。
我相信如果您只是不从子列表中删除不在测试列表中的东西,这个答案应该可以工作。 因此,对于那里提供的第一种方法
def contains(testList, subList):
shared = [x for x in testList if x in subList]
return shared == subList
您还可以将子列表转换为使用非列表输入。
def contains(testList, subList):
shared = [x for x in testList if x in subList]
return shared == list(subList)
您可以将列表转换为set()
组。 例子:
A = set(A)
B = set(B)
print(A <= B)
您可以a <= b
方法进行子集化。 好作品
您可以将collections.deque
用于O(n)
解决方案:
from collections import deque
def contains(a, b):
b = deque(b)
for i in a:
if b and i == b[0]:
_ = b.popleft()
return not bool(b)
data = [([1, 2, 3], [1, 2]), ([1, 3, 2], [1, 2]), ([1, 3, 2], [1, 4]), ([1, 3, 2], [2, 1])]
print([contains(*i) for i in data])
Output
[True, True, False, False]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.