我想将字符串与值列表匹配。它们可以重叠,例如string = "test1 test2"
和values = ["test1", "test1 test2"]
。
编辑:以下是我的完整代码,为一个简单的示例
import regex
string = "This is a test string"
values = ["test", "word", "string", "test string"]
pattern = r'\b({})\b'.format('|'.join(map(regex.escape, values)))
matches = set(map(str.lower, regex.findall(pattern, string, regex.IGNORECASE)))
output = ([x.upper() for x in values if x.lower() in matches])
print(output) # ['TEST', 'STRING']
# Expected output: ['TEST', 'STRING', 'TEST STRING']
答案 0 :(得分:1)
正如 Wiktor 所说,如果要查找所有匹配项,则不能 使用替代方法,因为正则表达式处理器会尝试连续的替代方法 并仅返回找到的第一个替代。
因此,您的程序必须对每个值使用单独模式进行测试, 但是出于性能原因,您可以预先编译所有它们。
我发现您的Python安装与我的安装之间的另一个区别
是import regex
。显然,您使用了一些较旧的Python版本,例如
我使用import re
(版本3.7)。我什至检查了Python版本2.7.15,
也使用import re
。
脚本如下所示:
import re
def mtch(pat, str):
s = pat.search(str)
return s.group().upper() if s else None
# Strings to look for
values = ["test", "word", "string", "test string"]
# Compile patterns
patterns = [ re.compile(r'\b({})\b'.format(re.escape(v)),
re.IGNORECASE) for v in values ]
# The string to check
string = "This is a test string"
# What has been found
list(filter(None, [ mtch(pat, string) for pat in patterns ]))
mtch
函数返回pat
找到的文本(已编译模式)
匹配中str
(源字符串)或 None 中失败。
patterns
包含已编译模式的列表。
然后有[ mtch(pat, string) for pat in patterns ]
个列表
理解,生成匹配结果列表(具有 None 值
如果匹配尝试失败)。
要过滤掉 None 个值,我使用了filter
函数。
最后list
收集所有过滤的字符串并打印:
['TEST', 'STRING', 'TEST STRING']
如果要对多个源字符串执行此搜索, 对每个源字符串仅运行最后一个语句,可能会添加 结果(以及搜索到的字符串的某种指示) 到一些结果列表。
如果源列表很长,则不应尝试全部阅读它们。 相反,您应该循环阅读它们并运行检查 仅适用于当前输入字符串。
我从您的评论中读到,读取字符串的代码如下:
with open("Test_data.csv") as f:
for entry in f:
entry = entry.split(',')
string = entry[2] + " " + entry[3] + " " + entry[6]
请注意,您在每个循环中都会覆盖string
,因此在循环结束后,
您从最后行(仅)获得了结果。
或者也许在阅读完之后,您就可以搜索当前模式 字符串?
另一个提示更改代码:
避免此类组合,例如entry
变量最初成立
整个字符串,然后是列表-拆分结果。
也许更具可读性的变体是:
for row in f:
entry = row.split(',')
在读取一行之后,然后再执行其他任何操作,请检查该行是否
刚刚阅读的不为空。如果该行为空,则将其忽略。
一种快速的测试方法是使用if
中的字符串(一个空字符串
计算为 False )。
for row in f:
if row:
entry = row.split(',')
...
在string = entry[2] + " " + entry[3] + " " + entry[6]
检查之前
entry
列表是否至少有7个项目(计数从0开始)。
也许您的某些输入行包含较小个片段
因此您的程序会尝试从不存在的元素中读取
此列表?
为了确定您要检查的字符串,请编写一个简短程序 仅 会拆分输入并打印结果字符串。然后看看它们,也许您发现问题了。
答案 1 :(得分:0)
如果您确定文本中包含foobar
,则无需分别在文本中搜索foo
和bar
:您已经知道答案了。
首先对您的搜索进行分组:
searches = ['test', 'word', 'string', 'test string', 'wo', 'wordy']
unique = set(searches)
ordered = sorted(unique, key = len)
grouped = {}
while unique:
s1 = ordered.pop()
if s1 in unique:
unique.remove(s1)
grouped[s1] = [s1]
redundant = [s2 for s2 in unique if s2 in s1]
for s2 in redundant:
unique.remove(s2)
grouped[s1].append(s2)
for s, dups in grouped.items():
print(s, dups)
# Output:
# test string ['test string', 'string', 'test']
# wordy ['wordy', 'word', 'wo']
将所有内容归类后,可以将搜索范围限制为仅顶层搜索(grouped
的键)。
此外,如果要考虑规模和性能,您是否真的需要正则表达式?您当前的示例可以使用更快的普通in
测试来处理。如果确实需要正则表达式,则对搜索进行分组的想法会比较困难-但在某些情况下可能并非不可能。