1

我有一组许多简单的 globbing 模式和整个单词,如下所示:

s = set(['ALE', 'BREAD*', 'BREAKFAST*', 'BROTH' ...])

我也是一大串词。我想检查此列表中的每个单词是否与 a) 集合中的通配模式或 b) 集合中的单词匹配。

如果没有 globbing 模式,我会做类似的事情:

for word in words:
    if word in s:
        # do something

但是由于该集合也包含通配符模式,如果我想将“BREADY”匹配到“BREAD*”,它将找不到匹配项

我能想到的唯一方法是使用嵌套的 for 循环将每个单词与集合中的每个模式进行比较。有没有一种方法可以检查每个单词在集合中是否有匹配项,而无需将其与集合中的每个元素进行比较?

4

3 回答 3

1

授予 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
于 2013-02-10T23:37:55.513 回答
1

您应该将要匹配的完整字符串与要匹配的前缀分开存储。对于您的前缀,将它们进一步划分为一组等长前缀(即一组长度为 1 的前缀、一组长度为 2 的前缀等)。

IE

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", ...])

完整的字符串匹配很简单 - 只需检查 if 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"
于 2013-02-10T23:14:20.617 回答
0

Suppose we have a wordlist words, and a search list searches. For the simple examples you gave, the following should suffice.

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
于 2013-02-10T23:07:24.417 回答