TLDR

如果您想要最快的基于正则表达式的解决方案,请使用此方法。 对于类似于OP的数据集,它比接受的答案快大约1000倍。

如果您不关心正则表达式,请使用此基于集合的版本,这比正则表达式联合快2000倍。

使用Trie优化正则表达式

由于正则表达式引擎在优化模式方面做得不是很好,因此简单的正则表达式联合方法会因许多被禁止的单词而变得缓慢。

可以使用所有被禁止的单词创建Trie并编写相应的正则表达式。 由此产生的trie或regex并不是人类可读的,但它们确实允许非常快速的查找和匹配。

['foobar', 'foobah', 'fooxar', 'foozap', 'fooza']

该列表转换为trie:

{

'f': {

'o': {

'o': {

'x': {

'a': {

'r': {

'': 1

}

}

},

'b': {

'a': {

'r': {

'': 1

},

'h': {

'': 1

}

}

},

'z': {

'a': {

'': 1,

'p': {

'': 1

}

}

}

}

}

}

}

然后到这个正则表达式模式:

r"\bfoo(?:ba[hr]|xar|zap?)\b"

最大的优点是,为了测试twopi是否匹配,正则表达式引擎只需要比较第一个字符(它不匹配),而不是尝试5个字。 这是一个5个单词的预处理矫枉过正,但它显示了数千个单词的有希望的结果。

请注意,使用了twopi非捕获组,因为:

twopi将匹配foobar或baz,但不是twopi

twopi会将不需要的信息保存到捕获组。

这是一个稍微修改过的要点,我们可以将其用作twopi库:

import re

class Trie():

"""Regex::Trie in Python. Creates a Trie out of a list of words. The trie can be exported to a Regex pattern.

The corresponding Regex should match much faster than a simple Regex union."""

def __init__(self):

self.data = {}

def add(self, word):

ref = self.data

for char in word:

ref[char] = char in ref and ref[char] or {}

ref = ref[char]

ref[''] = 1

def dump(self):

return self.data

def quote(self, char):

return re.escape(char)

def _pattern(self, pData):

data = pData

if "" in data and len(data.keys()) == 1:

return None

alt = []

cc = []

q = 0

for char in sorted(data.keys()):

if isinstance(data[char], dict):

try:

recurse = self._pattern(data[char])

alt.append(self.quote(char) + recurse)

except:

cc.append(self.quote(char))

else:

q = 1

cconly = not len(alt) > 0

if len(cc) > 0:

if len(cc) == 1:

alt.append(cc[0])

else:

alt.append('[' + ''.join(cc) + ']')

if len(alt) == 1:

result = alt[0]

else:

result = "(?:" + "|".join(alt) + ")"

if q:

if cconly:

result += "?"

else:

result = "(?:%s)?" % result

return result

def pattern(self):

return self._pattern(self.dump())

测试

这是一个小测试(与此相同):

# Encoding: utf-8

import re

import timeit

import random

from trie import Trie

with open('/usr/share/dict/american-english') as wordbook:

banned_words = [word.strip().lower() for word in wordbook]

random.shuffle(banned_words)

test_words = [

("Surely not a word", "#surely_NöTäWORD_so_regex_engine_can_return_fast"),

("First word", banned_words[0]),

("Last word", banned_words[-1]),

("Almost a word", "couldbeaword")

]

def trie_regex_from_words(words):

trie = Trie()

for word in words:

trie.add(word)

return re.compile(r"\b" + trie.pattern() + r"\b", re.IGNORECASE)

def find(word):

def fun():

return union.match(word)

return fun

for exp in range(1, 6):

print("\nTrieRegex of %d words" % 10**exp)

union = trie_regex_from_words(banned_words[:10**exp])

for description, test_word in test_words:

time = timeit.timeit(find(test_word), number=1000) * 1000

print(" %s : %.1fms" % (description, time))

它输出:

TrieRegex of 10 words

Surely not a word : 0.3ms

First word : 0.4ms

Last word : 0.5ms

Almost a word : 0.5ms

TrieRegex of 100 words

Surely not a word : 0.3ms

First word : 0.5ms

Last word : 0.9ms

Almost a word : 0.6ms

TrieRegex of 1000 words

Surely not a word : 0.3ms

First word : 0.7ms

Last word : 0.9ms

Almost a word : 1.1ms

TrieRegex of 10000 words

Surely not a word : 0.1ms

First word : 1.0ms

Last word : 1.2ms

Almost a word : 1.2ms

TrieRegex of 100000 words

Surely not a word : 0.3ms

First word : 1.2ms

Last word : 0.9ms

Almost a word : 1.6ms

有关信息,正则表达式开头如下:

????(:一个(:(:\' S |一个(:\' S |陈| liyah(:????\' S)| R(:dvark(? :(?:\' S | S))| ON))| b(:\' S | A(:??????C(:我们(:(:\&#39 ; S | ES))| [IK])|英尺|孤(:???(?:?\' S | S))| NDON(:( ?:编| ING |换货(:\ ?????' S)| S))| S(:E(:( ?:换货(:\' S)| [DS))| H(:(???? ?:E [DS] |荷兰国际集团))|荷兰国际集团)| T(:E(:( ?:换货(:\' S)| [DS]))|荷兰国际集团| toir(?????? :(?:\' S | S))))| b'(:如(:ID)| E(:SS(:(:??????\' S | ES) ?)| Y(?:?(:\' S | S)))| OT?(?:?(:\' S | T(?:\' S)?| ?S))| reviat(:?????E [DS] | I(:纳克|上(:(:\' S | S))))| Y(?:?\&#39 ; S)| \é?(?:?(:\' S | S)))| d(:?????ICAT(:E [DS] | I(:纳克|上(?: (?:\' S | S))))| OM(:????恩(:(:\' S | S))|伊纳勒)| U(?:CT(? :( ?: ED | I(:纳克|上(:(:????\' S | S)))|或(?:?(:\' S | S))? ?| S))| L(:\' s)))| E(:???(:\' S |上午| L(?:?(:\' S | ARD |子(?:\' s)))| R(?:???DEEN(:\' S)| nathy(?:??\' S)| RA (:???NT |和灰(:(:\' S | S))?))| T(:( ?:吨(:?????E(:R(:(:\& ????#39; S | S))| d)| ING |或(:(:\' S | S)))| S))| yance(:???\' S ?)| d))| HOR(:( ?: R(:E(为:n(:CE(:??????\' S)| T)| d)|荷兰国际集团)| S ?))| I(:????d(:E [DS] |荷兰国际集团|一月(:\' S))|盖尔| L(:???烯|它(:IES | Y(:\' S'))))| J〜(:ECT(:LY)| UR(:通货膨胀(:(:??????\' S | S))? | E [DS] |荷兰国际集团))| L(:一个(:略去(:(:????\' S | S))|???ZE)| E(:( ?: ST | ????R))| OOM | ution(:(:\' S | S))| Y)|米\' S | N(:????E(:GAT(:电子?[DS] | I(:?纳克|上(:\' S)?))| R(?:\' S))| ormal(:( ?:它(???? :IES | Y(?:\' S))| LY)))| O(:ARD |德(:(:??????\' S | S))|李( ?:SH |)|和灰(:(:\' S | IST(:(:( ?: E [DS]荷兰国际集团?)???(?:?\' S | S)) ?)))|米娜(:BL [EY] | T(:E [DS] | I(:纳克|上(:(:??????\' S | S))?)? ))| R(:????igin(:人(:(:\' S | S))| E'?(?:?(:\' S | S)))| ?吨(:( ?: ED | I(:纳克|上(:(:???\' S | IST(:(:???\' S | S))| S) ?)|阳离子)| S)))| U(:ND(:( ?:编| ING | S))| T)| VE(:(:??????\' S |板)))| R(:一个(:cadabra(:?????\' S)| d(:E [DS] |荷兰国际集团)|火腿(:???\' S) ?| M(?:?(:\' S | S))| SI(:????上(:(?:\' S | S))| VE(:(? :\' S | LY |岬(?:\' S)| S))))|东|腾讯科技讯(:?????E(:( ?:包换(:( ?: \' S | S))| [DS]))| ING |换货(:????(:\' S | S)))| O(:广告| GAT(???? ?:E [DS] | I(:???纳克|上(:(:\' S | S))?)))| UPT(:( ?: E(:?ST | r)的| LY |岬(?:\' S))))| S(:???ALOM | C(:ESS(:(:???\' S | E [DS] | ING ????))| ISSA(:(:\' S | [ES]))| OND(:( ?:编|在? ????克| S)))| EN(:CE(:(?:\' S | S))| T(:( ?: E(:E(:(:\???? ' S | ISM(?:\' S)| S))| d)| ING | LY | S)))| INTH(:?????(:\' S | E(?:\' S)))| O(:L(:UT(:E(:(:???????\' S | LY | ST))? | I(?:?上(:\' S)| SM(?:\' S)?))| v(?:E [DS] |荷兰国际集团))| R(α? :b(:( ?: E(为:n(:CY(:\' S)| T(:??????(?:?\' S | S)))| d )| ING | S))|?PTI ...

它真的难以理解,但是对于100000个被禁词的列表,这个Trie正则表达式比简单的正则表达式联合快1000倍!

这是一个完整的trie图,用trie-python-graphviz和graphviz twopi导出:

python3正则表达式替换_在Python 3中加速数百万的正则表达式替换相关推荐

  1. python查找excel中字符串_在Python问题中通过Excel搜索字符串/正则表达式

    我是So的新手,对Python比较陌生,所以如果这是一个简单的修复或不适当的问题,我很抱歉. 首先,我的程序通常可以工作,但我正试图实现一些冗余/捕获,以使其健壮. 该程序查看Excel文件的目录(和 ...

  2. mysql获取删除的条数_如何从mysql表中删除数百万条记录而不会减速

    有没有一种很好的方法来删除很多记录而不会减慢网站的速度? 我需要从没有索引和主键的MySQL表中删除数百万条记录.我阅读了SO和网上的各种教程,基本策略是限制删除查询,在删除之间休眠一两秒钟,然后重复 ...

  3. python字符串之查找与替换_在Python中查找和替换文本

    最简单的查找替换 在Python中查找和替换非常简单,如果当前对象是一个字符串str时,你可以使用该类型提供的find()或者index()方法查找指定的字符,如果能找到则会返回字符第一次出现的索引, ...

  4. php查询替换_如何在PHP中使用正则表达式进行查找替换

    1. preg_match - 执行一个正则表达式匹配int preg_match ( string $pattern , string $subject [, array &$matches ...

  5. python replace替换多个字符_关于python:使用string.replace(x,y)替换所有

    我刚刚开始学习python,并希望使用string.replace(x,y). 具体来说,根据字母是否最初大写,将所有内容全部替换为X和x. 例如 John S. Smith - > Xxxx ...

  6. python表达式中可以控制运算的优先顺序_在Python表达式中可以使用_______控制运算的优先顺序。...

    [填空题]Python中的大部分对象均为不可变对象,例如___________________________等,_ __________________________________等则为可变对象 ...

  7. python编程小知识_分享Python开发中要注意的十个小贴士

    大家请注意:这篇文中假设我们都用的是Python 3 1. 列表推导式 你有一个list:bag = [1, 2, 3, 4, 5] 现在你想让所有元素翻倍,让它看起来是这个样子:[2, 4, 6, ...

  8. java正则表达式性能_译:Java 中的正则表达式性能概述

    译者:Darren Luo 1. 概述 在本快速教程中,我们将展示模式匹配引擎是如何工作的.我们还将介绍在 Java 中优化正则表达式的不同方式. 有关正则表达式的的使用介绍,请参阅此文. 2. 模式 ...

  9. python编程口诀_少儿Python编程中的算术与技巧

    在儿童Python中,使用数值进行基本运算的情况很常见.加.减.乘.除都是内置的.加法和减法通过+和-号执行. 在Python shell提示中可以输入基本的算术表达式,将它当作一个计算机来使用.像计 ...

最新文章

  1. x86 下制作 ARM Docker 镜像,Docker Hub、Travis 自动构建 qemu-user-static
  2. Containers vs Serverless:怎么选择?
  3. idea加入springboot插件_带你搭一个SpringBoot+SpringData JPA的环境
  4. MFC 单文档如何修改背景。
  5. 适合小白的卷积神经网络图解
  6. 安装mariadb以及允许远程访问
  7. 论文浅尝 | 常识用于回答生成式多跳问题
  8. bat文件去掉变量 字符串中的空格
  9. 马云收购士兰微_马云出手!阿里36亿拿下千方科技
  10. 关于计算机的网络小说,“80后”从维熙:熟练电脑写作 关注网络文学
  11. 简历中的star法则
  12. DC Administration Services 宣布ISDA裁决委员会2020年申请流程
  13. flash垃圾回收和内存泄露
  14. 从联想ThinkStation工作站,窥见工具文明的新纪元
  15. 推荐给中学生的数学课外书:《写给全人类的数学魔法书》
  16. Qemu虚拟化PowerPc
  17. 7-29 喊山 (30 point(s))
  18. 现实世界充满了bug_现实世界充满了哪些bug
  19. ASP.NET Web API与Owin OAuth:使用Access Toke调用受保护的API
  20. 20201207杨辉三角(递归/枚举)

热门文章

  1. 今天终于知道了什么是X-window中字体hinting的含义了!
  2. jenkins-配置python
  3. Pandas 的melt函数解析
  4. 征信报告 加密文档_PDF文档如何加密?看完这个方法你就知道了
  5. ORA-22922: 不存在的 LOB 值 处理方法
  6. Python matplotlib 批量绘图内存不够问题(Out of memory)
  7. 十七道海量数据处理面试题与Bit-map详解
  8. 如此丝滑,Hive 中的各种常用 set 设置用起来就是爽啊
  9. Linux系列之soft lockup机制 浅析
  10. 20155214曾士轩 2016-2017-2 《Java程序设计》第1周学习总结