我有一组许多简单的globbing模式和完整的单词,比如:
s = set(['ALE', 'BREAD*', 'BREAKFAST*', 'BROTH' ...])
我还列出了一大堆单词。我想检查这个列表中的每个单词是否与a)集合中的globbing模式或b)集合中一个单词匹配。
如果没有球形图案,我只会做一些类似的事情:
for word in words:
if word in s:
# do something
但由于该集也包含球形图案,如果我想将"BREADY"与"BREAD*"匹配,它将找不到匹配项
我能想到的唯一方法是使用嵌套的for循环将每个单词与集合中的每个模式进行比较。有没有一种方法可以检查每个单词在集合中是否匹配,而无需将其与集合中的每个元素进行比较?
您应该将要匹配的完整字符串与要匹配的前缀分开存储。对于您的前缀,请将它们进一步划分为等长前缀集(即一组长度为1的前缀,一组长度2的前缀,等等)
即
fullstrings = set(["BREAKFAST", "LUNCH", "DINNER", ...])
prefixes_by_length = {} # dict of length -> prefix string
...
prefixes_by_length[4] = set(["CORN", "DESK", ...])
prefixes_by_length[5] = set(["BREAD", "TABLE", ...])
完整字符串匹配很简单,只需检查是否为word in fullstrings
即可。
对于前缀,您可以分别检查每个长度,从长度1开始到要匹配的最大前缀长度。对于每个长度n
,检查是否为word[:n] in prefixes_by_length[n]
。
如果你有很多前缀,这将比每次循环使用所有前缀有效得多。
for word in words:
if word in fullstrings:
"Match! do something"
for n in prefixes_by_length:
if word[:n] in prefixes_by_length[n]:
"Match! do something"
假设OP不想循环。
import re
import fnmatch
s = set(['ALE', 'BREAD*', 'BREAKFAST*', 'BROTH'])
patterns = [re.compile(fnmatch.translate(p)) for p in s]
for word in "BEING PALE I LIKE ALE WITH BREADDY ABROTH FOR BREAKFASTY TREATS AND BROTH".split():
for pattern in patterns:
if pattern.match(word):
print "HIT", word
提供:
HIT ALE
HIT BREADDY
HIT BREAKFASTY
HIT BROTH
假设我们有一个单词列表words
和一个搜索列表searches
。对于您给出的简单示例,以下内容就足够了。
for word in words:
for search in searches:
if search[-1] == "*":
search = search[:-1]
if word.lower().startswith(search.lower()):
yield word
else:
if word.lower() == search.lower():
yield word