Python:有没有找到哪个子串(来自一组子串)首先出现在字符串中的快捷方式?

时间:2016-04-21 09:52:04

标签: python string algorithm substring

让我们说,我有一个字符串:

s = "Hello, stack exchange. Let's solve my query"

让我们说我有3个子串

s1 = "solve"
s2 = "stack"
s3 = "Not present"

是否有快捷方式确定哪个子字符串首先出现在s?

我知道,我可以编写一个可以找到索引索引的函数,可能在字典中存储substr-index对,然后比较所有非负索引,但有没有更短的方式或pythonic方式这样做?

4 个答案:

答案 0 :(得分:4)

使用正则表达式获得此功能的另一种方法是:

import re
s = "Hello, stack exchange. Let's solve my query"
s1 = "solve"
s2 = "stack"
s3 = "Not present"
r1 = re.compile('|'.join([s1,s2,s3]))
r1.findall(s)

这将返回如下列表:

['stack', 'solve']

从列表索引中可以得到首先出现的搜索字符串。

答案 1 :(得分:2)

您可以使用生成器查找所有位置,并使用min()找到最左侧的位置:

positions = (s.find(sub), sub) for sub in (s1, s2, s3))
leftmost = min((pos, sub) for pos, sub in positions if pos > -1)[1]

这对每个子字符串只运行一次s.find(),过滤掉不存在的任何子字符串。如果根本没有子串匹配,min()将抛出ValueError异常;你可能想要抓住它。

这会扫描字符串3次;如果测试的子串数量足够大,你需要构建一个trie structure,将索引循环到s并测试该位置的字符是否存在于trie中:

def make_trie(*words):
     root = {}
     for word in words:
         current = root
         for letter in word:
             current = current.setdefault(letter, {})
         # insert sentinel at the end
         current[None] = None
     return root

def find_first(s, trie):
    for i in range(len(s)):
        pos, current, found = i, trie, []
        while pos < len(s) and s[pos] in current:
            found.append(s[pos])
            current = current[s[pos]]
            if None in current:  # whole substring detected
                return ''.join(found)
            pos += 1

leftmost = find_first(s, make_trie(s1, s2, s3))

trie可以重复使用多个字符串。

答案 2 :(得分:1)

这是执行此操作的最短路径。 创建一个正则表达式,并使用re.search在第一次匹配时中断。

import re
inputs = ['solve','stack','Not present']
s = "Hello, stack exchange. Let's solve my query"
match = re.search(re.compile('|'.join(inputs)),s)
print(match.group())
#returns 'stack'

演示:http://codepad.org/qoFtkQys

答案 3 :(得分:1)

你可以试试这个:

first_substr = min([(s.find(substr),substr) for substr in [s1, s2, s3] if s.find(substr)!=-1])[1]

由于