'.$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.
===== Encodage phonétique =====
Il existe différentes méthodes. Elles ont toutes leurs contraintes:
* Support plus ou moins bon des particularités des différentes langues.
* Implémentations supportant ou non l'UTF-8.
* Consommation CPU.
Liste non exhaustive:
* [[http://fr2.php.net/manual/fr/function.soundex.php|Soundex]]. Problème: Cet algo est surtout adapté à l'anglais, et il est limité à 4 caractères. Il existe des versions dérivées mieux adaptées au français:
* [[http://www.roudoudou.com/php/phonetic.php|Phonétique]] par Édouard BERGÉ.
* [[http://blog.mymind.fr/post/2007/03/15/Soundex-Francais|Soundex Français]] par Florent Bruneau.
* [[http://web.archive.org/web/20050209205529/http://www.php-help.net/sources-php/a.french.adapted.soundex.289.html|autre version]] d'un soundex adapté au français.
* [[http://fr2.php.net/manual/fr/function.metaphone.php|metaphone]]
* [[http://fr.wikipedia.org/wiki/Double_Metaphone|Double-metaphone]], qui est limité à 4 caractères, mais qui est censé être adapté à d'autres langues que l'anglais (langues slaves, germaniques, grec, français, Italien, espagnol, chinois et autres). Particularité: Il renvoie deux racines par mot, ce qui permet de faire des rapprochements. (voir l'[[http://swoodbridge.com/DoubleMetaPhone/|implémentation php]] de Stephen Woodbridge).
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 |
primary;
$dmp_sec = $dmp->secondary;
return array($t,soundex($t),trim(soundex_fr($t)),phonetique($t),metaphone($t),$dmp_prim,$dmp_sec);
}
echo <<
Mot soundex soundex_fr phonetique
metaphone doubleMetaphone (primary) doubleMetaphone (secondary)
EOF;
$mots = array('sceau','seau','sot','saut','wikipedia','éléphant','anticonstitutionnellement','athmosphérique','comportement');
foreach($mots as $mot)
{
echo ''.implode(' ',encode($mot)).' ';
}
echo '';
?>
$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:
* De la précision de l'algo choisi par rapport à la langue.
* Du nombre de suggestions que vous voulez ramener à l'utilisateur.
* De votre corpus (distribution des mots variée ou non, mélange de langues, quantité de données...)
===== Exemple =====
Petit exemple de recherche floue. Ce que fait ce programme d'exemple:
* Il charge en mémoire un dictionnaire français limité de [[http://www.freelang.com/dictionnaire/dic-francais.php|22740 mots]].
* Il compare le mot entré à ce dictionnaire avec la distance de levenshtein en encodant avec l'algo sélectionné (soundex,metaphone,soundex_fr ou phonétique)
* Il renvoie les mots ayant au plus 5% de différence avec le mot entré.
Voici le source (:!: **Ce script n'est pas sûr - à ne pas exécuter en environnement de production.**):