我想检查一个连字词是否以以下集合中的前缀开头。例如“去盐”。
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))
答案 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