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

时间:2014-06-03 14:08:27

标签: python string algorithm

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

这是一个比子串更弱的条件。例如,'iran'不是'爱尔兰'的子串,但它是一个子序列IRelANd。区别在于子序列不必是连续的。

更多例子:

  • 'indonesia'包含'india'。 INDonesIA
  • 'romania'包含'oman'。 rOMANia
  • 'malawi'包含'mali'。 MALawI

动画:我的朋友喜欢文字游戏。昨天我们玩了“国家内的国家”。如果我们错过任何配对,我很好奇。

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

  

子序列是一个序列,可以通过删除一些元素而不改变其余元素的顺序从另一个序列派生

5 个答案:

答案 0 :(得分:38)

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')

也适用于任何迭代:

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

<强>更新

Stefan Pochmann建议这样做。

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

两个版本都使用迭代器;迭代器产生在前一次迭代中未产生的项目。

例如:

>>> 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)

继续寻找潜在子序列的下一个角色,从最后找到的角色开始。只要在字符串的其余部分中找不到其中一个字符,它就没有子序列。如果可以通过这种方式找到所有字符,那就是:

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

答案 2 :(得分:1)

我做了

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

答案 3 :(得分:-1)

我试图理解falsetru的解决方案,并且实质上使用iter简化了以下操作:

def is_subseq(sub, string):
    i = 0
    for c in string:
        if i == len(sub):
            break
        if sub[i] == c:
            i += 1
    if i != len(sub):
        return False
    return True


def is_subseq2(sub, string):
    j = 0
    count = 0
    for c in sub:
        if j == len(string):
            return False
        while j < len(string) and string[j] != c:
            j += 1
        if string[j] == c:
            count += 1
    return count == len(sub)

答案 4 :(得分:-2)

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