如果只是检查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。
我应该如何解决这个问题?
答案 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
您甚至可以使用all
和any
在一(两行)行中完成此操作:
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