Soundex 2 francais

Description

Bon ben ceci est une première version de soundex2, un soundex francisé.
Il est basé sur un algo décrit ici : http://sqlpro.developpez.com/cours/soundex/ par Frédéric BROUARD.

Il n'est pas encore parfait (j'ai dû manquer 2-3 choses), mais il tourne déjà pas mal.
Il faudra aussi l'optimiser car il risque d'être gourmand, à la longue...!

Soundex est une méthode utilisé pour comparer phonétiquement 2 chaînes. Il existe en natif dans PHP les fonction soundex, ou metaphone, mais elles sont anglicisées.

Cette version-ci est francisé, donc prend en compte les spécificités de la langue française.

PRECISIONS SUR L'UTILITE :
Ces algo, soundex, soundex2, phonex, metaphone, assigne un code à une chaîne donnée. Ce code est calculé en fonction de la phonétique, donc de la prononciation de cette chaîne.
En l'occurence, les 2 algo présents par défaut dans php, soundex () et metaphone () ne prennent en compte que la prononciation anglaise.
celui-ci, basé sur soundex2 (un algo plus performant que soundex), est francisé, donc prend en compte la prononciation française.

Evidemment, 2 chaînes différentes peuvent avoir le même code. Par exemple, ici, 'gros' aura le même code soundex2 que 'grau'.
Ce qui veut dire, dans le cadre d'une recherche sur une base de données contenant des noms, par exemple, on peut effecyuer une recherche phonétique aussi! Bref, le mec a parlé avec un cilent par téléphone, mais il ne s'est pas comment s'écrit exactement son nom de famille...gros, graus, grau, graux, greaux...? etc... Il tapoe par exemple gros, et effectue une recherche soundex. Cette recherche lui ressortira tous les noms dont le code soundex est le même que 'gros'. Donc si le client s'appelait 'Graux', il le trouvera.

Couplé à l'algo de levenshtein (fonction interne php) en plus, on peut avoir une recherche phonétique par pertinence...les codes identiques en premiers, puis ceux un peu différents, etc...jusqu'à un degré de différence voulu.

Le mieux, dans le cadre d'une bdd, est évidemment de stocker le code soundex2 dans la base, histoire de ne pas le recalculer à chaque recherche (pour info, sur ma bécane, 10000 tours de boucle sur le tableau que j'ai mis en exemple dans index.php, donc 10000 * 11 chaînes dont on doit calculer le code soundex2, ça me prend une 20aine de secondes. Et encore, je n'ai pas optimisé l'algo).

Source / Exemple :


<?php
/**


*

  • author Johan Barbier <barbier_johan@hotmail.com>
  • /
class soundex2 { /**
  • public sString
  • main string we work on
  • /
public $sString = ''; /**
  • vowels replacement array
  • /
private $aReplaceVoy1 = array ( 'E' => 'A', 'I' => 'A', 'O' => 'A', 'U' => 'A' ); /**
  • consonnants replacement array
  • /
private $aReplaceGrp1 = array ( 'GUI' => 'KI', 'GUE' => 'KE', 'GA' => 'KA', 'GO' => 'KO', 'GU' => 'K', 'CA' => 'KA', 'CO' => 'KO', 'CU' => 'KU', 'Q' => 'K', 'CC' => 'K', 'CK' => 'K' ); /**
  • other replacement array
  • /
private $aReplaceGrp2 = array ( 'ASA' => 'AZA', 'KN' => 'NN', 'PF' => 'FF', 'PH' => 'FF', 'SCH' => 'SSS' ); /**
  • endings replacement array
  • /
private $aEnd = array ( 'A', 'T', 'D', 'S' ); /**
  • public function build
  • core function of the class, go through the whole process
  • @Param string sString : the string we want to check
  • /
public function build ($sString) { /**
  • let's check it's a real string...
  • /
if (is_string ($sString)) { $this -> sString = $sString; } /**
  • remove starting and ending spaces
  • /
$this -> sString = trim ($this -> sString); /**
  • remove special french characters
  • /
$this -> trimAccent (); /**
  • string to upper case
  • /
$this -> sString = strtoupper ($this -> sString ); /**
  • let's remove every space in the string
  • /
$this -> sString = str_replace (' ', '', $this -> sString); /**
  • let's remove every '-' in the string
  • /
$this -> sString = str_replace ('-', '', $this -> sString); /**
  • let's process through the first replacement array
  • /
$this -> arrReplace ($this -> aReplaceGrp1); /**
  • let's process through th vowels replacement
  • /
$sChar = substr ($this -> sString, 0, 1); $this -> sString = substr ($this -> sString, 1, strlen ($this -> sString) - 1); $this -> arrReplace ($this -> aReplaceVoy1); $this -> sString = $sChar.$this -> sString; /**
  • let's process through the second replacement array
  • /
$this -> arrReplace ($this -> aReplaceGrp2, true); /**
  • let's remove every 'H' but those prededed by a 'C' or an 'S'
  • /
$this -> sString = preg_replace ('/(?<![CS])H/', '', $this -> sString); /**
  • let's remove every 'Y' but those preceded by an 'A'
  • /
$this -> sString = preg_replace ('/(?<!A)Y/', '', $this -> sString); /**
  • remove endings in aEnd
  • /
$length = strlen ($this -> sString) - 1; if (in_array ($this -> sString{$length}, $this -> aEnd)) { $this -> sString = substr ($this -> sString, 0, $length); } /**
  • let's remove every 'A', but the one at the beginning of the string, if any.
  • /
$sChar = ''; if ($this -> sString{0} === 'A') { $sChar = 'A'; } $this -> sString = str_replace ('A', '', $this -> sString); $this -> sString = $sChar.$this -> sString; /**
  • let's have only 1 occurence of each letter
  • /
$this -> sString = preg_replace( '`(.)\1`', '$1', $this -> sString ); /**
  • let's have the final code : a 4 letters string
  • /
$this -> getFinal (); } /**
  • private function getFinal
  • gets the first 4 letters, pads the string with white space if the string length < 4
  • /
private function getFinal () { if (strlen ($this -> sString) < 4) { $this -> sString = str_pad ($this -> sString, 4, ' ', STR_PAD_RIGHT); } else { $this -> sString = substr ($this -> sString, 0, 4); } } /**
  • private function trimAccent
  • remove every special French letters
  • /
private function trimAccent () { $this -> sString = htmlentities(strtolower($this -> sString )); $this -> sString = preg_replace("/&(.)(acute|cedil|circ|ring|tilde|uml|grave);/", "$1", $this -> sString ); $this -> sString = preg_replace("/([^a-z0-9]+)/", "-", html_entity_decode($this -> sString )); $this -> sString = trim($this -> sString , "-"); } /**
  • private function arrReplace
  • replacement method, given an array
  • @Param array tab : the replacement array to be used
  • @Param bool pref : if false, just replace keys by values; if true, do the same but only with prefix
  • /
private function arrReplace (array $tab, $pref = false) { $fromRep = array_keys ($tab); $toRep = array_values ($tab); if (false === $pref) { $this -> sString = str_replace ($fromRep, $toRep, $this -> sString); } else { foreach ($fromRep as $clef => $val) { $length = strlen ($val); if (substr ($this -> sString, 0, $length) === $val) { $this -> sString = substr_replace ($this -> sString, $toRep[$clef], 0, $length); } } } } } ?>

Codes Sources

A voir également

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.