检查字符串是否是名称的可能缩写

时间:2011-09-07 09:20:03

标签: python string-matching slug abbreviation text-analysis

我正在尝试开发一个python算法来检查字符串是否可以是另一个单词的缩写。例如

  • fckfc kopenhavn的匹配项,因为它匹配单词的前几个字符。 fhk不匹配。
  • fco不应与fc kopenhavn匹配,因为没有人会将FC Kopenhavn缩写为FCO。
  • irlin real life匹配。
  • ifkifk goteborg匹配。
  • aikallmanna idrottskluben匹配。
  • aidallmanna idrottsklubben匹配。这不是一个真正的团队名称缩写,但我想除非您应用有关如何形成瑞典语缩写的领域特定知识,否则很难将其排除。
  • manumanchester united匹配。

很难描述算法的确切规则,但我希望我的例子展示我所追求的目标。

更新我在显示匹配字母大写的字符串时犯了一个错误。在实际场景中,所有字母都是小写的,所以它不像检查哪些字母是大写字母那么容易。

5 个答案:

答案 0 :(得分:11)

这会通过所有测试,包括我创建的一些额外测试。它使用递归。以下是我使用的规则:

  • 缩写的第一个字母必须与第一个字母相匹配 文字
  • 缩写的其余部分(缩写减去第一个字母)必须是以下缩写:

    • 其余的话,或
    • 从中开始的剩余文字 第一个单词中的任何位置。

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

答案 1 :(得分:4)

这是一种完成你似乎想要做的事的方法

import re    
def is_abbrev(abbrev, text):
    pattern = ".*".join(abbrev.lower())
    return re.match("^" + pattern, text.lower()) is not None

插入符号确保缩写的第一个字符与单词的第一个字符匹配,对于大多数缩写词应该是正确的。

修改: 您的新更新稍微改变了规则。使用"(|.*\s)"代替".*"时,缩写中的字符只有在彼此相邻时才会匹配,或者下一个字符出现在新单词的开头。

这会将fckFC Kopenhavn正确匹配,但fco则不会。 但是,将aikallmanna idrottskluben匹配将工作,因为这需要了解瑞典语并且不是那么简单。

这是带有次要修改的新代码

import re    
def is_abbrev(abbrev, text):
    pattern = "(|.*\s)".join(abbrev.lower())
    return re.match("^" + pattern, text.lower()) is not None

答案 2 :(得分:4)

@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

你必须定义你的逻辑,你不能盲目找到缩写。

答案 3 :(得分:0)

您的算法看似简单 - 缩写是所有大写字母的连接。 这样:

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()

答案 4 :(得分:0)

这可能已经足够了。

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')