关于python:如何测试一个字符串是否是另一个字符串的子序列?

How to test if one string is a subsequence of another?

本问题已经有最佳答案,请猛点这里访问。

如何测试一个字符串是否是另一个字符串的子序列?

与子字符串相比,这是一个较弱的条件。例如," iran"不是" ireland"的子字符串,而是子序列IRelANd。区别在于子序列不必连续。

更多示例:

  • "印度尼西亚"包含"印度"。 INDonesIA
  • "罗马尼亚"包含"阿曼"。 rOMANia
  • " malawi"包含" mali"。 MALawI

旅行:我的朋友喜欢文字游戏。昨天我们打了"国家内部的国家"。我很好奇我们是否错过了任何对。

编辑:如果您不熟悉子序列的数学定义

A subsequence is a sequence that can be derived from another sequence by deleting some elements without changing the order of the remaining elements


1
2
3
4
5
6
7
8
9
10
def is_subseq(x, y):
    it = iter(y)
    return all(any(c == ch for c in it) for ch in x)

assert is_subseq('india', 'indonesia')
assert is_subseq('oman', 'romania')
assert is_subseq('mali', 'malawi')
assert not is_subseq('mali', 'banana')
assert not is_subseq('ais', 'indonesia')
assert not is_subseq('ca', 'abc')

也可用于任何可迭代项:

1
2
assert is_subseq(['i', 'n', 'd', 'i', 'a'],
                 ['i', 'n', 'd', 'o', 'n', 'e', 's', 'i', 'a'])

更新

Stefan Pochmann提出了这个建议。

1
2
3
def is_subseq(x, y):
    it = iter(y)
    return all(c in it for c in x)

两个版本都使用迭代器;迭代器产生的项目不是上一次迭代中产生的。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
>>> it = iter([1,2,3,4])
>>> for x in it:
...     print(x)
...     break
...
1
>>> for x in it:  # `1` is yielded in previous iteration. It's not yielded here.
...     print(x)
...
2
3
4


只需继续寻找可能的子序列的下一个字符,就从最后一个发现的字符开始。一旦在字符串的其余部分找不到一个字符,就没有子序列。如果可以通过这种方式找到所有字符,则为:

1
2
3
4
5
6
def is_subsequence(needle, haystack):
    current_pos = 0
    for c in needle:
        current_pos = haystack.find(c, current_pos) + 1
        if current_pos == 0 : return False
    return True

我做到了

1
2
3
4
5
6
7
8
def is_subsequence(x, y):
   """Test whether x is a subsequence of y"""
    x = list(x)
    for letter in y:
        if x and x[0] == letter:
            x.pop(0)

    return not x


1
2
3
4
5
6
7
8
9
def subsequence(seq, subseq):
    seq = seq.lower()
    subseq = subseq.lower()
    for char in subseq:
        try:      
            seq = seq[seq.index(char)+1:]            
        except:
            return False
    return True