检查字符串是不是是名称的可能缩写
Posted
技术标签:
【中文标题】检查字符串是不是是名称的可能缩写【英文标题】:Check if a string is a possible abbrevation for a name检查字符串是否是名称的可能缩写 【发布时间】:2011-11-11 23:41:04 【问题描述】:我正在尝试开发一种 python 算法来检查一个字符串是否可以是另一个单词的缩写。例如
fck
与 fc kopenhavn
匹配,因为它匹配单词的第一个字符。 fhk
不匹配。
fco
不应匹配 fc kopenhavn
,因为没有人会将 FC Kopenhavn 缩写为 FCO。
irl
与 in real life
匹配。
ifk
与 ifk goteborg
匹配。
aik
与 allmanna idrottskluben
匹配。
aid
与 allmanna idrottsklubben
匹配。这不是一个真正的团队名称缩写,但我想除非您应用有关瑞典缩写如何形成的领域特定知识,否则很难排除它。
manu
与 manchester united
匹配。
很难描述算法的确切规则,但我希望我的例子能说明我所追求的。
更新我在显示匹配字母大写的字符串时犯了一个错误。在实际场景中,所有字母都是小写的,所以并不像检查哪些字母是大写那么简单。
【问题讨论】:
所以你想看看字符串是否只匹配那些字符串中的大写字母?如果是这样,请尝试为它编写一些内容:只获取完整内容的大写字母并将它们放在字典中(作为具有完整版本作为值的键),然后查找起来很容易。事实上,你还没有真正问过问题...... 我能想到的最好的办法是提取所有大写字母,将短字符串转换为大写,然后进行相等测试。 半加时赛:ManU 可以被视为对曼联球迷的侮辱,尽管它在非英语国家被广泛用作缩写。 我认为这是不可能的,例如您应该如何确定aik
有效,但aid
无效?
【参考方案1】:
@Ocaso Protal
在评论how should you decide that aik is valid, but aid is not valid?
中说他是对的。
我想到的算法是使用word threshold
(用空格分隔的单词数)。
words = string.strip().split()
if len(words) > 2:
#take first letter of every word
elif len(words) == 2:
#take two letters from first word and one letter from other
else:
#we have single word, take first three letter or as you like
你必须定义你的逻辑,你不能盲目地找到缩写。
【讨论】:
【参考方案2】:这通过了所有测试,包括我创建的一些额外测试。它使用递归。以下是我使用的规则:
缩写的第一个字母必须与 文字缩写的其余部分(缩写减去第一个字母)必须是以下的缩写:
剩余的单词,或 剩余的文本从 第一个单词中的任何位置。tests=(
('fck','fc kopenhavn',True),
('fco','fc kopenhavn',False),
('irl','in real life',True),
('irnl','in real life',False),
('ifk','ifk gotebork',True),
('ifko','ifk gotebork',False),
('aik','allmanna idrottskluben',True),
('aid','allmanna idrottskluben',True),
('manu','manchester united',True),
('fz','faz zoo',True),
('fzz','faz zoo',True),
('fzzz','faz zoo',False),
)
def is_abbrev(abbrev, text):
abbrev=abbrev.lower()
text=text.lower()
words=text.split()
if not abbrev:
return True
if abbrev and not text:
return False
if abbrev[0]!=text[0]:
return False
else:
return (is_abbrev(abbrev[1:],' '.join(words[1:])) or
any(is_abbrev(abbrev[1:],text[i+1:])
for i in range(len(words[0]))))
for abbrev,text,answer in tests:
result=is_abbrev(abbrev,text)
print(abbrev,text,result,answer)
assert result==answer
【讨论】:
该死,比我快 30 秒 :) +1 对不起,所有的字符串都应该是小写的。原文全部小写。【参考方案3】:这是一种完成您似乎想做的事情的方法
import re
def is_abbrev(abbrev, text):
pattern = ".*".join(abbrev.lower())
return re.match("^" + pattern, text.lower()) is not None
插入符号确保缩写的第一个字符与单词的第一个字符匹配,对于大多数缩写来说应该是正确的。
编辑:
您的新更新稍微改变了规则。通过使用"(|.*\s)"
而不是".*"
,缩写中的字符只有在它们彼此相邻或下一个字符出现在新单词的开头时才会匹配。
这将正确匹配fck
和FC Kopenhavn
,但fco
不会。
但是,将aik
与allmanna idrottskluben
匹配将不起作用,因为这需要瑞典语言知识并且不是那么简单。
这是新的代码,稍作修改
import re
def is_abbrev(abbrev, text):
pattern = "(|.*\s)".join(abbrev.lower())
return re.match("^" + pattern, text.lower()) is not None
【讨论】:
【参考方案4】:这可能已经足够了。
def is_abbrevation(abbrevation, word):
lowword = word.lower()
lowabbr = abbrevation.lower()
for c in lowabbr:
if c not in lowword:
return False
return True
print is_abbrevation('fck', 'FC Kopenhavn')
【讨论】:
这是不正确的,例如试试print is_abbrevation('fkc', 'FC Kopenhavn')
【参考方案5】:
您的算法看起来很简单 - 缩写是所有大写字母的串联。 所以:
upper_case_letters = "QWERTYUIOPASDFGHJKLZXCVBNM"
abbrevation = ""
for letter in word_i_want_to_check:
if letter in letters:
abbrevation += letter
for abb in _list_of_abbrevations:
if abb=abbrevation:
great_success()
【讨论】:
你可以使用string.ascii_uppercase
以上是关于检查字符串是不是是名称的可能缩写的主要内容,如果未能解决你的问题,请参考以下文章