检查一个字符串中的字母是否在另一个字符串中按顺序排列

时间:2018-11-14 11:12:11

标签: python string python-3.x python-2.7 for-loop

如果只是检查test_string中的字母是否也在control_string中,则

我不会遇到这个问题。

我将只使用下面的代码。

if set(test_string.lower()) <= set(control_string.lower()):
    return True

但是我还面临着一个相当复杂的任务,即确定

中的重叠字母是否为

control_string的顺序与test_string中的顺序相同。

例如,

test_string = 'Dih'
control_string = 'Danish'
True

test_string = 'Tbl'
control_string = 'Bottle'
False

我曾考虑过使用for迭代器来比较字母的索引,但是很难想到合适的算法。

for i in test_string.lower():
    for j in control_string.lower():
        if i==j:
            index_factor = control_string.index(j)

我的计划是将主索引因子与下一个因子进行比较,如果主索引因子结果大于另一个索引因子,则该函数返回False。

我坚持如何在for循环中比较那些index_factors。

我应该如何解决这个问题?

6 个答案:

答案 0 :(得分:5)

您可以将join字符串中的字符test换成regular expression,并允许介于.*之间的任何其他字符,然后re.search control字符串中的模式。

>>> test, control = "Dih", "Danish"
>>> re.search('.*'.join(test), control) is not None
True
>>> test, control = "Tbl", "Bottle"
>>> re.search('.*'.join(test), control) is not None
False

无需使用正则表达式,就可以从iter字符串创建一个control,并使用两个嵌套循环, 1) break从内部循环和else返回False,直到在test中找到control中的所有字符为止。即使iter已经可以迭代,创建control也很重要,这样内部循环才能在上次停止的地方继续。

def check(test, control):
    it = iter(control)
    for a in test:
        for b in it:
            if a == b:
                break
        else:
            return False
    return True

您甚至可以使用allany在一(两行)行中完成此操作:

def check(test, control):
    it = iter(control)
    return all(any(a == b for b in it) for a in test)

两种方法的复杂度应为O(n),其中n为最大字符数。

1)从概念上讲,它类似于@jpp所做的事情,但是恕我直言更加清晰。

答案 1 :(得分:3)

这是一个解决方案。这个想法是迭代control字符串 first ,如果它匹配下一个test字符,则产生一个值。如果匹配的总数等于test的长度,则满足您的条件。

def yield_in_order(x, y):
    iterstr = iter(x)
    current = next(iterstr)
    for i in y:
        if i == current:
            yield i
            current = next(iterstr)

def checker(test, control):
    x = test.lower()
    return sum(1 for _ in zip(x, yield_in_order(x, control.lower()))) == len(x)

test1, control1 = 'Tbl', 'Bottle'
test2, control2 = 'Dih', 'Danish'

print(checker(test1, control1))  # False
print(checker(test2, control2))  # True

@tobias_k's answer的版本更干净。如果您需要其他信息,例如如何许多字母在找到中断之前对齐,您可以轻松调整checker函数以返回sum(1 for _ in zip(x, yield_in_order(...)))

答案 2 :(得分:0)

递归是解决此类问题的最佳方法。 这是检查顺序顺序的一个。

def sequentialOrder(test_string, control_string, len1, len2): 

    if len1 == 0:     # base case 1
        return True

    if len2 == 0:     # base case 2
        return False

    if test_string[len1 - 1] == control_string[len2 - 1]: 
        return sequentialOrder(test_string, control_string, len1 - 1, len2 - 1)  # Recursion 

    return sequentialOrder(test_string, control_string, len1, len2-1)

test_string = 'Dih'
control_string = 'Danish'

print(isSubSequence(test_string, control_string, len(test_string), len(control_string)))

输出:

True

False

test_string = 'Tbl'
control_string = 'Bottle'

这是一种执行相同操作的迭代方法,

def sequentialOrder(test_string,control_string,len1,len2): 

    i = 0
    j = 0

    while j < len1 and i < len2: 
        if test_string[j] == control_string[i]:     
            j = j + 1    
        i = i + 1

    return j==len1 

test_string = 'Dih'
control_string = 'Danish'

print(sequentialOrder(test_string,control_string,len(test_string) ,len(control_string)))

答案 3 :(得分:0)

一种简单的方法是利用key中的sorted参数,该参数用作排序比较的键:

def seq_order(l1, l2):
    intersection = ''.join(sorted(set(l1) & set(l2), key = l2.index))
    return True if intersection == l1 else False

因此,这是计算两个集合的交集并根据较长的字符串对其进行排序。这样,您只需要将结果与较短的字符串进行比较,看看它们是否相同。

该函数相应地返回True或False。使用示例:

seq_order('Dih', 'Danish')
#True

seq_order('Tbl', 'Bottle')
#False

seq_order('alp','apple')
#False

答案 4 :(得分:0)

使用生成器的优雅解决方案:

def foo(test_string, control_string):
    if all(c in control_string for c in test_string):
        gen = (char for char in control_string if char in test_string)
        if all(x == test_string[i] for i, x in enumerate(gen)):
            return True
    return False

print(foo('Dzn','Dahis')) # False
print(foo('Dsi','Dahis')) # False
print(foo('Dis','Dahis')) # True

首先检查test_string中是否包含所有字母。然后检查该顺序是否类似于control_string的顺序。

答案 5 :(得分:0)

您可以使用find(letter, last_index)在处理后的字母之后查找所需字母的出现。

def same_order_in(test, control):
    index = 0
    control = control.lower()
    for i in test.lower():
        index = control.find(i, index)
        if index == -1:
            return False
        # index += 1 # uncomment to check multiple occurrences of same letter in test string  
    return True

如果测试字符串具有重复的字母,例如:

test_string = 'Diih'
control_string = 'Danish'

带有注释行same_order_in(test_string, control_string) == True

并带有未注释的行same_order_in(test_string, control_string) == False