Проверьте, является ли строка возможным сокращением имени - PullRequest
10 голосов
/ 07 сентября 2011

Я пытаюсь разработать алгоритм 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.

Трудно описать точные правила алгоритма, но я надеюсь, что мои примеры показывают, чего я добиваюсь.

Обновление Я сделал ошибку, показываястроки с соответствующими буквами в верхнем регистре.В реальном сценарии все буквы в нижнем регистре, поэтому это не так просто, как просто проверить, какие буквы в верхнем регистре.

Ответы [ 5 ]

11 голосов
/ 07 сентября 2011

Это проходит все тесты, включая несколько дополнительных, которые я создал.Использует рекурсию.Вот правила, которые я использовал:

  • Первая буква аббревиатуры должна соответствовать первой букве текста
  • Остальная часть аббревиатуры (аббревиатура минуспервая буква) должна быть сокращением для:

    • оставшихся слов или
    • оставшегося текста, начиная с любой позиции в первом слове.

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
4 голосов
/ 07 сентября 2011

@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

Вы должны определить свою логику, вы не можете найти аббревиатуру вслепую.

4 голосов
/ 07 сентября 2011

Вот способ выполнить то, что вы, кажется, хотите сделать

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
0 голосов
/ 07 сентября 2011

Это может быть достаточно хорошо.

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')
0 голосов
/ 07 сентября 2011

Ваш алгоритм кажется простым - сокращение - это объединение всех заглавных букв. так:

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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...