Dans différentes applications on a besoin d'effectuer des recherches. Il peut parfois être utile de retourner des résultats dont l'orthographe ou la phonétique sont proches (par exemple, retourner "wikipedia" pour "wikipdia", ou "sceau" pour "sot").
Il existe différentes méthodes. La plus utilisée combine un encodage phonétique (soundex ou autres) et un calcul de distance (Levenshtein).
Cette méthode consiste à calculer la distance entre deux mots.
php est fourni en standard avec cette fonction. Exemple:
<?php header('content-type: text/plain'); function distance($a,$b) { echo $a.'->'.$b.' : '.levenshtein($a,$b)."\n"; } distance('wikipedia','wikipedia'); distance('wikepedia','wikipedia'); distance('wikepdia','wikipedia'); ?>
Ce qui donne ceci:
wikipedia->wikipedia : 0 wikepedia->wikipedia : 1 wikepdia->wikipedia : 2
Attention: Cette fonction est sensible à la casse. Ainsi la distance entre 'wikipedia' et 'WIKIPEDIA' est de 9. Il convient donc de tout passer en minuscules avant de calculer la distance:
levenshtein(strtolower($a),strtolower($b));
Toutefois, levenshtein ne règle pas le problème des mots ayant la même sonorité mais avec une orthographe différente. Il convient alors d'encoder phonétiquement les mots.
Il existe différentes méthodes. Elles ont toutes leurs contraintes:
Liste non exhaustive:
Voici quelques exemples d'encodages phonétiques:
Mot | soundex | soundex_fr (Florent Bruneau) | Phonetique (Édouard BERGÉ) | metaphone | doubleMetaphone (primary) | doubleMetaphone (secondary) |
---|---|---|---|---|---|---|
sceau | S000 | SO | SO | S | S | S |
seau | S000 | SO | SO | S | S | S |
sot | S300 | SO | SO | ST | ST | ST |
saut | S300 | SO | SO | ST | ST | ST |
wikipedia | W213 | VKPD | OUIKIPEDIA | WKPT | AKPT | FKPT |
éléphant | L153 | ELF | ELEFAN | LFNT | LFNT | LFNT |
anticonstitutionnellement | A532 | ATKO | ANTIKONSTITUSION | ANTKNSTTXNLMNT | ANTK | ANTK |
athmosphérique | A352 | AT0F | ATMOSFERIK | A0MSFRK | A0MS | ATMS |
comportement | C516 | KOPO | KONPORTEMAN | KMPRTMNT | KMPR | KMPR |
Il devient alors intéressant de calculer la distance levenshtein sur ces codes.
On voit clairement que les algos adaptés aux français donnent de meilleurs résultats. Les autres bottent en touche, généralement, en supprimant les voyelles (accentuées ou non), ce qui leur donne un taux de réussite correcte malgré tout (même si, comme on le voit, elles ne gèrent pas les consonnes sourdes, comme le "t" dans le mot "sot").
Notez que (heureusement), ces algos ignorent les différences minuscules/majuscules.
Ce qui est généralement pratiqué pour la recherche floue:
$phon1 = soundex_fr($mot1); $phon2 = soundex_fr($mot2); $pourcentage = levenshtein($phon1,$phon2)*100/strlen($mot1); if ($pourcentage<=25) echo $mot2.' est proche de '.$mot1
Le seuil est à choisir en fonction:
Petit exemple de recherche floue. Ce que fait ce programme d'exemple:
Voici le source ( Ce script n'est pas sûr - à ne pas exécuter en environnement de production.):
Et pour que cela soit plus simple: voici le fichier zip: test_phonetique.zip
Exemple d'utilisation:
En cherchant le mot "raté" avec Soundex:
Avec metaphone:
Avec soundex_fr:
Avec Phonétique:
Comme on peut le constater:
Le choix de l'algo est un compromis entre la qualité des résultats et la charge CPU. Notez que:
A prendre en considération (non traité ici)