检查单词是否以某些前缀开头的最有效方法是什么?

时间:2019-03-07 23:42:55

标签: python regex

我想检查一个连字词是否以以下集合中的前缀开头。例如“去盐”。

prefixes = {
    'de-', 'dis-', 'il-', 'im-', 'ir-', 'inter-',
    'mid-', 'mis-', 'non-', 'pre-', 'pro-', 're-',
    'semi-', 'sub-', 'tele-', 'trans-',
    'un-', 'e-'
}

这是我的代码:

def prefix(word):
    match = re.match(r"[a-z]+-",word)
    if match:
        if match.group() in prefixes:
            return True
word = "e-mail"
print(prefix(word))

3 个答案:

答案 0 :(得分:2)

您可以先对前缀进行排序,以便可以使用bisect.bisect_left方法在前缀中找到小于 O(log n)时间复杂度的给定单词的最接近单词:

from bisect import bisect_left
prefixes = sorted(prefixes)
def prefix(prefixes, word):
    i = bisect_left(prefixes, word)
    if i and word.startswith(prefixes[i - 1]):
        return prefixes[i - 1]
    raise ValueError("No prefix found for '%s'." % word)

这样:

print(prefix(prefixes, 'non-word'))
print(prefix(prefixes, 'tele-video'))
print(prefix(prefixes, 'e-mail'))

输出:

non-
tele-
e-

答案 1 :(得分:2)

Bisect的缩放比这更好。但是运行时不会考虑比较前缀。 (如果您为前缀考虑相似的前缀,则为Runtime = O(n log(n))。但是对于示例而言,这是一个更好的解决方案。)


最有效的方法是 仅使用前n个字符(n =最大长度前缀)[可选:状态机也可以为您执行此操作] 并将每个字母都交给状态机。

状态机将需要确定仍然可以获取哪些前缀。

E.g. to be tested: "prefix" with your list of prefixes
You start with "" -> everything is possible
You read the "p" -> {pro, pre} are possible prefixes now
You read the "r" -> still the same, both start with "pr"
You read the "e" -> pro is not possible and pre has been found.

可以从前缀列表中生成状态机。但是我不会去讨论。

但是它会导致一个状态和一个过渡表,该表和过渡表取决于当前状态和下一个读取的字符。

An example:
Let me add prof to your list of prefixes.

0:
p -> 1
? -> to be added, there are more prefixes

1:
r -> 2
? -> terminate, nothing found

2:
e -> terminate, found pre
o -> 3, found pro
? -> -1

3:
f -> terminate, found pro and prof
? -> terminate, found pro

如何阅读:     州:     读取字符->下一个状态,找到     ? =其他

答案 2 :(得分:1)

在您的情况下,我认为散列会很有效。

m=set()
for x in prefixes:
    m.add(x.split(‘-‘)[0])

return word.split(‘-‘)[0] in m