6 python regex string performance
我被要求找到给定字符串中出现的子字符串总数(不区分大小写,带/不带标点符号)。一些例子:
count_occurrences("Text with", "This is an example text with more than +100 lines") # Should return 1
count_occurrences("'example text'", "This is an 'example text' with more than +100 lines") # Should return 1
count_occurrences("more than", "This is an example 'text' with (more than) +100 lines") # Should return 1
count_occurrences("clock", "its 3o'clock in the morning") # Should return 0
Run Code Online (Sandbox Code Playgroud)
我选择了正则表达式,.count()
因为我需要完全匹配,最后得到:
def count_occurrences(word, text):
pattern = f"(?<![a-z])((?<!')|(?<='')){word}(?![a-z])((?!')|(?=''))"
return len(re.findall(pattern, text, re.IGNORECASE))
Run Code Online (Sandbox Code Playgroud)
我得到了所有匹配的计数,但我的代码0.10secs
在预期时间是0.025secs
. 我错过了什么吗?有没有更好的(性能优化的)方法来做到这一点?
好吧,我正在努力让它在没有正则表达式的情况下工作,因为我们都知道正则表达式很慢。这是我想出的:
\ndef count_occurrences(word, text):\n spaces = [\' \', \'\\n\', \'(\', \'\xc2\xab\', \'\\u201d\', \'\\u201c\', \':\', "\'\'", "__"]\n endings = spaces + [\'?\', \'.\', \'!\', \',\', \')\', \'"\', \'\xc2\xbb\']\n s = text.lower().split(word.lower())\n l = len(s)\n return sum((\n (i == 0 and (s[0] == \'\' or any(s[i].endswith(t) for t in spaces)) and (s[1] == \'\' or any(s[i+1].startswith(t) for t in endings))) \n or (i == l - 2 and any(s[i].endswith(t) for t in spaces) and (s[i+1] == \'\' or any(s[i+1].startswith(t) for t in endings)))\n or (i != 0 and i != l - 2 and any(s[i].endswith(t) for t in spaces) and any(s[i+1].startswith(t) for t in endings))\n ) for i in range(l - 1))\n
Run Code Online (Sandbox Code Playgroud)\n整个文件在 ideone 中运行:
\nRan 1 test in 0.025s\n\nOK\n
Run Code Online (Sandbox Code Playgroud)\n这就是问题所要问的。
\n逻辑非常简单。让我们拆分 by text
,word
都是小写的。现在让我们看看每对邻居。例如,如果索引 0 以有效分隔符结束,索引 1 以有效分隔符开头,则将其计为一次出现。让我们一直这样做到分裂的最后几个。
spaces
由于性能在这里很重要,因此我们必须注意和的顺序endings
。我们基本上是在寻找列表中第一个满足条件的。因此,首先找到更常见的变量很重要。例如,如果我声明:
spaces = [\'(\', \'\xc2\xab\', \'\\u201d\', \'\\u201c\', \':\', "\'\'", "__", \'\\n\', \' \']\n
Run Code Online (Sandbox Code Playgroud)\n我得到的不是我的解决方案中的内容,而是几0.036
秒钟的时间。
例如,如果我声明一个数组:
\nspaces = [\' \', \'\\n\', \'(\', \'\xc2\xab\', \'\\u201d\', \'\\u201c\', \':\', "\'\'", "__", \'?\', \'.\', \'!\', \',\', \')\', \'"\', \'\xc2\xbb\']\n
Run Code Online (Sandbox Code Playgroud)\n它具有所有分隔符并且仅使用它,我得到 0.053 秒。这比我的解决方案多了 60%。
\n以另一种顺序声明分隔符可能有更好的解决方案。
\n 归档时间: |
|
查看次数: |
406 次 |
最近记录: |