繁体   English   中英

考虑顺序如何检查列表(字符串)是否包含另一个列表(字符串)

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM