python3正则表达式替换_在Python 3中加速数百万的正则表达式替换
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中加速数百万的正则表达式替换相关推荐
- python查找excel中字符串_在Python问题中通过Excel搜索字符串/正则表达式
我是So的新手,对Python比较陌生,所以如果这是一个简单的修复或不适当的问题,我很抱歉. 首先,我的程序通常可以工作,但我正试图实现一些冗余/捕获,以使其健壮. 该程序查看Excel文件的目录(和 ...
- mysql获取删除的条数_如何从mysql表中删除数百万条记录而不会减速
有没有一种很好的方法来删除很多记录而不会减慢网站的速度? 我需要从没有索引和主键的MySQL表中删除数百万条记录.我阅读了SO和网上的各种教程,基本策略是限制删除查询,在删除之间休眠一两秒钟,然后重复 ...
- python字符串之查找与替换_在Python中查找和替换文本
最简单的查找替换 在Python中查找和替换非常简单,如果当前对象是一个字符串str时,你可以使用该类型提供的find()或者index()方法查找指定的字符,如果能找到则会返回字符第一次出现的索引, ...
- php查询替换_如何在PHP中使用正则表达式进行查找替换
1. preg_match - 执行一个正则表达式匹配int preg_match ( string $pattern , string $subject [, array &$matches ...
- python replace替换多个字符_关于python:使用string.replace(x,y)替换所有
我刚刚开始学习python,并希望使用string.replace(x,y). 具体来说,根据字母是否最初大写,将所有内容全部替换为X和x. 例如 John S. Smith - > Xxxx ...
- python表达式中可以控制运算的优先顺序_在Python表达式中可以使用_______控制运算的优先顺序。...
[填空题]Python中的大部分对象均为不可变对象,例如___________________________等,_ __________________________________等则为可变对象 ...
- python编程小知识_分享Python开发中要注意的十个小贴士
大家请注意:这篇文中假设我们都用的是Python 3 1. 列表推导式 你有一个list:bag = [1, 2, 3, 4, 5] 现在你想让所有元素翻倍,让它看起来是这个样子:[2, 4, 6, ...
- java正则表达式性能_译:Java 中的正则表达式性能概述
译者:Darren Luo 1. 概述 在本快速教程中,我们将展示模式匹配引擎是如何工作的.我们还将介绍在 Java 中优化正则表达式的不同方式. 有关正则表达式的的使用介绍,请参阅此文. 2. 模式 ...
- python编程口诀_少儿Python编程中的算术与技巧
在儿童Python中,使用数值进行基本运算的情况很常见.加.减.乘.除都是内置的.加法和减法通过+和-号执行. 在Python shell提示中可以输入基本的算术表达式,将它当作一个计算机来使用.像计 ...
最新文章
- x86 下制作 ARM Docker 镜像,Docker Hub、Travis 自动构建 qemu-user-static
- Containers vs Serverless:怎么选择?
- idea加入springboot插件_带你搭一个SpringBoot+SpringData JPA的环境
- MFC 单文档如何修改背景。
- 适合小白的卷积神经网络图解
- 安装mariadb以及允许远程访问
- 论文浅尝 | 常识用于回答生成式多跳问题
- bat文件去掉变量 字符串中的空格
- 马云收购士兰微_马云出手!阿里36亿拿下千方科技
- 关于计算机的网络小说,“80后”从维熙:熟练电脑写作 关注网络文学
- 简历中的star法则
- DC Administration Services 宣布ISDA裁决委员会2020年申请流程
- flash垃圾回收和内存泄露
- 从联想ThinkStation工作站,窥见工具文明的新纪元
- 推荐给中学生的数学课外书:《写给全人类的数学魔法书》
- Qemu虚拟化PowerPc
- 7-29 喊山 (30 point(s))
- 现实世界充满了bug_现实世界充满了哪些bug
- ASP.NET Web API与Owin OAuth:使用Access Toke调用受保护的API
- 20201207杨辉三角(递归/枚举)
热门文章
- 今天终于知道了什么是X-window中字体hinting的含义了!
- jenkins-配置python
- Pandas 的melt函数解析
- 征信报告 加密文档_PDF文档如何加密?看完这个方法你就知道了
- ORA-22922: 不存在的 LOB 值 处理方法
- Python matplotlib 批量绘图内存不够问题(Out of memory)
- 十七道海量数据处理面试题与Bit-map详解
- 如此丝滑,Hive 中的各种常用 set 设置用起来就是爽啊
- Linux系列之soft lockup机制 浅析
- 20155214曾士轩 2016-2017-2 《Java程序设计》第1周学习总结