Python:匹配字符串中的多个子字符串
我正在使用Python,希望将给定字符串与多个子字符串匹配。我试图用两种不同的方法来解决这个问题。我的第一个解决方案是将子字符串与字符串匹配,如下所示:Python:匹配字符串中的多个子字符串,python,regex,python-3.x,string,substring,Python,Regex,Python 3.x,String,Substring,我正在使用Python,希望将给定字符串与多个子字符串匹配。我试图用两种不同的方法来解决这个问题。我的第一个解决方案是将子字符串与字符串匹配,如下所示: str = "This is a test string from which I want to match multiple substrings" value = ["test", "match", "multiple", "ring"] temp = [] temp.extend([x.upper() for x in value if
str = "This is a test string from which I want to match multiple substrings"
value = ["test", "match", "multiple", "ring"]
temp = []
temp.extend([x.upper() for x in value if x.lower() in str.lower()])
print(temp)
这将导致temp=[“测试”、“匹配”、“多个”、“环”]
然而,这不是我想要的结果。子字符串应该完全匹配,因此“环”不应该与“字符串”匹配
这就是我试图用正则表达式解决这个问题的原因,如下所示:
str = "This is a test string from which I want to match multiple substrings"
value = ["test", "match", "multiple", "ring"]
temp = []
temp.extend([x.upper() for x in value if regex.search(r"\b" + regex.escape(x) + r"\b", str,
regex.IGNORECASE) is not None])
print(temp)
str = ['Hi,', 'how', 'are', 'you?']`
values = ['how', 'you', 'time', 'space']
new_str = []
for word in str:
for j in values:
if word.startswith(j):
new_str.append(word)
# result -> ['how', 'you?']
结果是[“测试”、“匹配”、“多个”],这是正确的解决方案。尽管如此,这个解决方案的计算时间太长。我必须对大约100万个字符串进行检查,使用regex的解决方案需要几天才能完成,而使用第一个解决方案需要1.5个小时
我想知道是否有办法让第一个解决方案工作,或者让第二个解决方案运行得更快。提前谢谢
编辑:
value
也可以包含数字,或者像“test1 test2”这样的短短语您可以按空格拆分str
,然后将value
中的元素与=
匹配
编辑:
所以你说
值中的一些字符串可以在它们之前或之后有空格。您可以通过以下行解决此问题:
values = [i.strip() for i in values]
这将删除字符串前后的所有空白字符(对于每个元素)
此外,您还提到,如果您将str
按空格拆分,一些单词会在拆分过程中留下标点符号-->“你好吗?”
将导致['Hi','how','are','you']
。您可以通过使用字符串startswith()
内置方法从值中筛选以元素开头的所有单词来解决此问题,如下所示:
str = "This is a test string from which I want to match multiple substrings"
value = ["test", "match", "multiple", "ring"]
temp = []
temp.extend([x.upper() for x in value if regex.search(r"\b" + regex.escape(x) + r"\b", str,
regex.IGNORECASE) is not None])
print(temp)
str = ['Hi,', 'how', 'are', 'you?']`
values = ['how', 'you', 'time', 'space']
new_str = []
for word in str:
for j in values:
if word.startswith(j):
new_str.append(word)
# result -> ['how', 'you?']
然后,您可以使用一些正则表达式从结果列表中删除标点符号,但现在您将有更小的列表可供迭代。删除所有标点符号后,就可以按照我在原始答案中的建议匹配整个字符串
我希望现在更清楚。在没有看到实际数据的情况下,很难提出最佳解决方案,但您可以尝试以下方法:
- 生成一个匹配所有值的模式。这样,您只需要搜索字符串一次(而不是每个值搜索一次)
- 跳过转义值,除非它们包含特殊字符(如
'^'
或'*'
)
- 将结果直接分配给
temp
,避免使用temp.extend()
进行不必要的复制
我想到了两种可能的优化:
- 使用
re.compile
预编译模式,这样它就不会在每次调用match
时重新编译李>
- 与其与四个独立的正则表达式匹配,不如创建一个与所有值匹配的正则表达式
结果:
['TEST', 'MATCH', 'TEST1 TEST2', 'MULTIPLE']
这种方法的潜在缺点:
- 输出的顺序可能不同。您最初的方法将结果按其在
值中出现的顺序排列。这种方法将结果按其在str
中的显示顺序排列
- 如果相同的值在
str
中多次出现,则该值将在temp
中多次出现。与原始方法相反,该方法中的值最多在temp
中出现一次
搜索
一旦找到匹配项就会终止findall
始终搜索整个字符串。如果您希望大多数字符串与值中的每个单词匹配,并且希望大多数匹配项出现在字符串的早期,则findall
可能比搜索
慢。另一方面,如果您希望搜索经常出现None
,那么findall
可能会更快一些李>
通过编译您的解决方案并在您的计算机上运行编译后的版本,您可能可以节省大量时间strings@jeremycg“编译您的解决方案”的确切含义是什么?但当值包含诸如“test1 test2”之类的子字符串时,这不起作用。因此,如果value有一个单词包含在str
中,那么应该有一个匹配?使用@Kevin在他的回答中提到的re.compile
,如果value
的元素包含空格,或者如果句子包含一个本来应该匹配的单词旁边的标点符号,那么你就可以做value=[i.strip()表示i in值]
并使用字符串方法startswith()从str
中筛选项目
然后从筛选列表中删除标点符号并查看结果。对不起,我不确定我是否理解。您能否在答案中编辑一些完整的代码并演示其工作原理?谢谢您的编辑,但我认为我仍然缺少一些内容。当我运行该代码块时,我得到了名称错误:名称“I”未定义
。“所以你说值中的某些字符串可以在它们之前或之后有空格。”我不认为他是这么说的。我认为他是说值中可以有空格,不一定在开头或结尾。例如,test1 test2包含空格。删除它是错误的,因为“test1 test2”不应匹配,将其拆分为多个元素是错误的,因为“test1”不应匹配,除非它紧跟在“test2”后面的空格之前.“编译”模式在这里不会带来任何好处,因为您只使用了一次。即使多次使用,也很可能忽略不计。我对实际问题的解释是,必须搜索数百万个字符串,而不仅仅是示例代码中的字符串。假设有一个f或者以百万字符串表示的str:
紧跟在mytemp=[]
之后的一行。感谢您的回答,但这是您的第一个选择