当前位置: 首页 > 面试题库 >

在Python中找到几个子字符串之一的最有效方法是什么?

巫晋鹏
2023-03-14
问题内容

我有一个可能的子字符串的列表,例如['cat', 'fish', 'dog']。实际上,该列表包含数百个条目。

我正在处理一个字符串,我正在寻找的是找到这些子字符串中任何一个的第一次出现的索引。

澄清'012cat'一下,结果是3,'0123dog789cat'结果是4。

我还需要知道找到了哪个子字符串(例如,其在子字符串列表中的索引或文本本身),或者至少是匹配的子字符串的长度。

有很明显的暴力方式可以实现这一目标,我想知道是否有任何优雅的Python / regex解决方案。


问题答案:

我认为正则表达式比单独检查每个子字符串要好,因为 从概念上讲
,正则表达式被建模为DFA,并且随着输入被消耗,所有匹配项都将同时被测试(导致对输入字符串进行一次扫描) )。

因此,这是一个示例:

import re

def work():
  to_find = re.compile("cat|fish|dog")
  search_str = "blah fish cat dog haha"
  match_obj = to_find.search(search_str)
  the_index = match_obj.start()  # produces 5, the index of fish
  which_word_matched = match_obj.group()  # "fish"
  # Note, if no match, match_obj is None

更新: 将单词组合成单个备选单词模式时应 格外
小心。以下代码构建了一个正则表达式,但转义了所有正则表达式特殊字符并对单词进行排序,以便较长的单词有机会在同一单词的任何较短前缀之前匹配:

def wordlist_to_regex(words):
    escaped = map(re.escape, words)
    combined = '|'.join(sorted(escaped, key=len, reverse=True))
    return re.compile(combined)

>>> r.search('smash atomic particles').span()
(6, 10)
>>> r.search('visit usenet:comp.lang.python today').span()
(13, 29)
>>> r.search('a north\south division').span()
(2, 13)
>>> r.search('012cat').span()
(3, 6)
>>> r.search('0123dog789cat').span()
(4, 7)

结束更新

应该注意的是,您将希望尽可能少地形成正则表达式(即,调用re.compile())。最好的情况是,您提前知道搜索的内容(或者您一次/很少计算一次),然后将re.compile的结果保存在某个地方。我的示例只是一个简单的废话功能,因此您可以看到正则表达式的用法。这里还有更多正则表达式文档:

http://docs.python.org/library/re.html

希望这可以帮助。

更新: 我不确定python如何实现正则表达式,但要回答Rax有关re.compile()是否存在限制的问题(例如,您可以尝试同时将“
|”一起匹配的单词数)
,以及运行编译的时间:这似乎都不是问题。我试用了这段代码,足以说服我。(我可以通过添加时间安排和报告结果,以及将单词列表放入集合中以确保没有重复…来做得更好,但是这两项改进似乎都太过分了)。这段代码基本上是瞬时运行的,使我确信可以搜索2000个单词(大小为10),并且这些单词都将匹配。这是代码:

import random
import re
import string
import sys

def main(args):
    words = []
    letters_and_digits = "%s%s" % (string.letters, string.digits)
    for i in range(2000):
        chars = []
        for j in range(10):
            chars.append(random.choice(letters_and_digits))
        words.append(("%s"*10) % tuple(chars))
    search_for = re.compile("|".join(words))
    first, middle, last = words[0], words[len(words) / 2], words[-1]
    search_string = "%s, %s, %s" % (last, middle, first)
    match_obj = search_for.search(search_string)
    if match_obj is None:
        print "Ahhhg"
        return
    index = match_obj.start()
    which = match_obj.group()
    if index != 0:
        print "ahhhg"
        return
    if words[-1] != which:
        print "ahhg"
        return

    print "success!!! Generated 2000 random words, compiled re, and was able to perform matches."

if __name__ == "__main__":
    main(sys.argv)

更新: 应该注意的是,在正则表达式中进行或运算的事物的顺序很 重要
。看看以下受TZOTZIOY启发的测试

>>> search_str = "01catdog"
>>> test1 = re.compile("cat|catdog")
>>> match1 = test1.search(search_str)
>>> match1.group()
'cat'
>>> match1.start()
2
>>> test2 = re.compile("catdog|cat")  # reverse order
>>> match2 = test2.search(search_str)
>>> match2.group()
'catdog'
>>> match2.start()
2

这表明顺序很重要:-/。我不确定这对Rax的应用意味着什么,但是至少行为是已知的。



 类似资料:
  • 问题内容: 我在尝试搜索字符串中的子字符串时遇到问题。该子字符串可能在字符串中也可能不在字符串中。 我知道是否可以完成的两种方法是: 正则表达式 但是,还有其他“优化”方式吗?你会怎么做? Ruby可以提供更好的答案吗?由于我们使用jRuby,因此答案可以是Ruby或Java。 问题答案: 在Ruby中,使用方法: 返回。

  • 问题内容: 有人可以向我解释一种有效的方法来找到Python(2.7)中数字的所有因素吗? 我可以创建一个算法来执行此操作,但是我认为它的编码很差,并且花费大量时间才能生成大量结果。 问题答案: 这将很快返回所有因素。 为什么以平方根为上限? 。因此,如果两个因素相同,则它们都是平方根。如果使一个因子变大,则必须使另一个因子变小。这意味着这两个之一将始终小于或等于,因此您只需要搜索到该点即可找到两

  • 问题内容: 我有2列的大型表格:Id和Title。ID为bigint,我可以自由选择“标题”列的类型:varchar,char,text等。列标题包含随机文本字符串,例如“ abcdefg”,“ q”,“ allyourbasebelongtous”,最多255个字符。 我的任务是通过给定的子字符串获取字符串。子字符串也具有随机长度,可以是字符串的开头,中间或结尾。最明显的执行方式: 我不在乎IN

  • 我需要在一个字符串中找到许多子字符串。我下载了一个网页并把它放入一个字符串中。然后我要看看页面是否包含一些字符串(子字符串)。 现在我在boost库中使用正则表达式,因为我使用它来使用正则表达式模式([0-9]等)。 问题是:如果我只需要在一个字符串中找到一个子字符串,哪种方法是最快的?

  • 问题内容: 如何找到两个子字符串之间的字符串? 我当前的方法是这样的: 但是,这似乎效率很低而且不合Python。什么是做这样的更好的方法? 忘了提:该字符串可能无法启动,并最终和。他们之前和之后的字符可能更多。 问题答案:

  • 我需要以最有效的方式替换一个字符串中许多不同的子字符串。除了使用string.replace替换每个字段的蛮力方法之外,还有其他方法吗?