Domanda

Sto cercando di sviluppare un algoritmo Python per verificare se una stringa potrebbe essere un'abbreviazione per un'altra parola. Ad esempio

  • fck è una corrispondenza per fc kopenhavn perché corrisponde ai primi caratteri della parola. fhk non corrisponderebbe.
  • fco non deve corrispondere a fc kopenhavn perché nessuno irl potrebbe abbreviare FC Kopenhavn come FCO.
  • irl è una corrispondenza per in real life.
  • ifk è una corrispondenza per ifk goteborg.
  • aik è una corrispondenza per allmanna idrottskluben.
  • aid è una corrispondenza per allmanna idrottsklubben. Questa non è una vera abbreviazione del nome del team, ma immagino che sia difficile escluderla a meno che non applichi una conoscenza specifica del dominio su come vengono formate le abbreviazioni svedesi.
  • manu è una corrispondenza per manchester united.

È difficile descrivere le regole esatte dell'algoritmo, ma spero che i miei esempi mostrino ciò che sto cercando.

Aggiorna Ho commesso un errore nel mostrare le stringhe con le lettere corrispondenti in maiuscolo. Nello scenario reale, tutte le lettere sono minuscole, quindi non è facile come controllare solo quali lettere sono maiuscole.

È stato utile?

Soluzione

Questo supera tutti i test, inclusi alcuni extra che ho creato.Usa la ricorsione.Ecco le regole che ho usato:

  • La prima lettera dell'abbreviazione deve corrispondere alla prima lettera di il testo
  • Il resto dell'abbreviazione (l'abbrevia meno la prima lettera) deve essere un'abbreviazione per:

    • le restanti parole o
    • il testo rimanente a partire da qualsiasi posizione nella prima parola.

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

Altri suggerimenti

Ecco un modo per realizzare ciò che sembra che tu voglia fare

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

Il carattere accento circonflesso assicura che il primo carattere dell'abbreviazione corrisponda al primo carattere della parola, dovrebbe essere vero per la maggior parte delle abbreviazioni.

Modifica : Il tuo nuovo aggiornamento ha cambiato un po 'le regole.Utilizzando "(|.*\s)" invece di ".*", i caratteri nell'abbreviazione corrisponderanno solo se sono uno accanto all'altro o se il carattere successivo appare all'inizio di una nuova parola.

Questo abbinerà correttamente fck con FC Kopenhavn, ma fco no. Tuttavia, l'abbinamento di aik con allmanna idrottskluben non funzionerà, poiché richiede la conoscenza della lingua svedese e non è così banale da fare.

Ecco il nuovo codice con la modifica minore

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

@Ocaso Protal ha detto nel commento how should you decide that aik is valid, but aid is not valid? e ha ragione.

L'algoritmo che mi è venuto in mente è di lavorare con word threshold (numero di parole separate da spazio).

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

devi definire la tua logica, non riesci a trovare l'abbreviazione alla cieca.

Il tuo algoritmo sembra semplice: l'abbreviazione è la concatenazione di tutte le lettere maiuscole. quindi:

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

Potrebbe essere abbastanza buono.

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')
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top