Controlla se una stringa è una possibile abbreviazione di un nome
-
27-10-2019 - |
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 perfc kopenhavn
perché corrisponde ai primi caratteri della parola.fhk
non corrisponderebbe. -
fco
non deve corrispondere afc kopenhavn
perché nessuno irl potrebbe abbreviare FC Kopenhavn come FCO. -
irl
è una corrispondenza perin real life
. -
ifk
è una corrispondenza perifk goteborg
. -
aik
è una corrispondenza perallmanna idrottskluben
. -
aid
è una corrispondenza perallmanna 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 permanchester 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.
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')