Fonction qui génère un code grâce à l'ortographe et la prononciation d'un mot

Soyez le premier à donner votre avis sur cette source.

Snippet vu 4 662 fois - Téléchargée 19 fois

Contenu du snippet

Je souhaite vous faire part d'une fonction que j'ai écrite dans le cadre de mon stage pour permettre de trier facilement des noms en fonction de leur orthographe. Grâce au code générer par cette fonction j'alimente un champs dans ma BDD et je peux faire des tris très rapide pour ainsi détecter des doublons. Cette fonction est un mélange de mon imagination et de soundexfr() implémenter en pl-sql sur(http://dgriessinger.developpez.com/postgresql/udf/?page=chaines). Libre a vous de choisir le nombre de caractère générer par la fonction. Le couplage de my_soundex() avec le codage des n premier caractère (ici n = 4) est beaucoup plus performant que my_soundex() seule. Profiter en ! Elle est assez performante, pour info sur 15 000 champs dans ma BDD auxquels j'ai appliqué cette fonction j'ai mis 25sec.

Source / Exemple :


//------------------------------------------------------------------
//Génère un hashcode en fonction de l'orthographe et de la prononciation d'un nom
function ds_hasherNom($nom){
	
	//On retire les caractères spéciaux et accentués, on met en minuscules
	$nom = stringRemoveAccent($nom);
	$nom = strtr($nom,"._/\<>-|(){}[]*&\"''$;?!","                       ");
	$nom=strtolower($nom);
	//On enlève les espaces
	$st = '';
	for($i=0;$i<strlen($nom);$i++){
		if($nom{$i} != ' '){
			$st.=$nom{$i};	
		}
	}
	//On codes les 4 premiers caractères sur 2 chiffres chacun
	$code = '';	
	for($i=0;$i<4;$i++){
		$ch = $st{$i};
		$mcar = '';
		switch($ch){
			case '0':$mcar.='00';break;
			case '1':$mcar.='01';break;
			case '2':$mcar.='02';break;
			case '3':$mcar.='03';break;
			case '4':$mcar.='04';break;
			case '5':$mcar.='05';break;
			case '6':$mcar.='06';break;
			case '7':$mcar.='07';break;
			case '8':$mcar.='08';break;
			case '9':$mcar.='09';break;
			case 'a':$mcar.='10';break;
			case 'b':$mcar.='11';break;
			case 'c':$mcar.='12';break;
			case 'd':$mcar.='13';break;
			case 'e':$mcar.='14';break;
			case 'f':$mcar.='15';break;
			case 'g':$mcar.='16';break;
			case 'h':$mcar.='17';break;
			case 'i':$mcar.='18';break;
			case 'j':$mcar.='19';break;
			case 'k':$mcar.='20';break;
			case 'l':$mcar.='21';break;
			case 'm':$mcar.='22';break;
			case 'n':$mcar.='23';break;
			case 'o':$mcar.='24';break;
			case 'p':$mcar.='25';break;
			case 'q':$mcar.='26';break;
			case 'r':$mcar.='27';break;
			case 's':$mcar.='28';break;
			case 't':$mcar.='29';break;
			case 'u':$mcar.='30';break;
			case 'v':$mcar.='31';break;
			case 'w':$mcar.='32';break;
			case 'x':$mcar.='33';break;
			case 'y':$mcar.='34';break;
			case 'z':$mcar.='35';break;
		}
		$code.=$mcar;
	}	
	//On récupère la fin du nom
	$fin = substr($st,4);
	$fin = strtoupper($fin);		
	//On applique la fonction soundex() sur la fin du nom
	//Si la fin du mot existe (+ de 4 lettres)
	if(strlen($fin)>0){
		$code.=my_soundex($fin);
	}else {
		$code.='00000';
	}
	return $code;
}

//------------------------------------------------------------------
//Supprime les accents d'une chaîne
function stringRemoveAccent($string){
	$result='';
	$length=mb_strlen($string);
	for($i=0;$i<$length;$i++)
		switch($char=mb_substr($string,$i,1,'utf-8')){
			case 'ä':
			case 'à':
			case 'â':$result.='a';break;
			case 'é':
			case 'è':
			case 'ê':
			case 'ë':$result.='e';break;
			case 'î':
			case 'ï':$result.='i';break;
			case 'ô':
			case 'œ':
			case 'ö':$result.='o';break;
			case 'ü':
			case 'ù':
			case 'û':$result.='u';break;
			case 'ÿ':$result.='y';break;
			case 'Ä':
			case 'À':
			case 'Â':$result.='A';break;
			case 'ñ':$result.='n';break;
			case 'É':
			case 'È':
			case 'Ê':
			case 'Ë':$result.='E';break;
			case 'Î':
			case 'Ï':$result.='I';break;
			case 'Ô':
			case 'Œ':
			case 'Ö':$result.='O';break;
			case 'Ü':
			case 'Ù':
			case 'Û':$result.='U';break;
			case 'ç':$result.='c';break;
			case 'Ç':$result.='C';break;
			case 'Ÿ':$result.='Y';break;
			case 'æ':$result.='a';break;
			case 'Æ':$result.='a';break;
			default:$result.=$char;
		} 
	return $result;
}

//------------------------------------------------------------------
//Fonction qui attribut un code de 5 caractères à une consonance phonétique
function my_soundex($str){
	$st='';
	//Recherche de la 1ere consomne
	for($i=0;$i<strlen($str);$i++){
		$ch = substr($str,$i,1);
		if($ch != 'A' && $ch != 'E' && $ch != 'I' && $ch != 'O' && $ch != 'U' && $ch != 'Y' && $ch != 'H' && $ch != 'W'){
			$st.= $ch;
		}
	}
	$st2 = substr($st,0,1);
	
	//Codage des consonnes suivantes
	for($i=1;$i<strlen($st);$i++){
		$ch = substr($st,$i,1);
		switch($ch){
			case 'B':
			case 'P':$st2.='1';break;
			case 'C':
			case 'K':
			case 'Q':$st2.='2';break;
			case 'D':
			case 'T':$st2.='3';break;
			case 'L':$st2.='4';break;
			case 'M':
			case 'N':$st2.='5';break;
			case 'R':$st2.='6';break;
			case 'G':
			case 'J':$st2.='7';break;
			case 'S':
			case 'X':
			case 'Z':$st2.='8';break;
			case 'F':
			case 'V':$st2.='9';break;
		}
	}
	
	//Si le code est moins long que 5 caractère on comble par des 0	
	if(strlen($st2)<5){
		$st2=str_pad($st2,5,'0');
	}
	//Sinon on garde seulement les 5 premiers caractères
	elseif(strlen($st2)>5){
		$st2 = substr($st2,0,5);
	}
	return $st2;
}

Conclusion :


Vos impressions, vos remarques?

A voir également

Ajouter un commentaire Commentaires
kankrelune Messages postés 1293 Date d'inscription mardi 9 novembre 2004 Statut Membre Dernière intervention 21 mai 2015
22 juin 2009 à 23:35
Slt Foofymany... tout à fait d'accord mon commentaire sur le strtr() concerne le str_replace... si tu travaille sur du muli-byte il va de soit qu'il faut passer par l'extension mb_string... .. .

Par contre je persiste pour le strlen() dans la condition de tes for... tant que la chaine testée n'est pas remaniée dans la boucle même, ce qui est le cas ici, il ne faut surtout pas mettre ton strlen() dans la partie conditionnelle de ta boucle for... imagine tu fais 10000 itération ça te fait 9999 strlen() pour rien... c'est un détail mais qui a son importance... .. .

Au passage $st{$i} est déprécié et n'existera bientôt plus => $st[$i]

Pour le reste rien a redire ne l'ayant pas testé... .. .

@ tchaOo°
cs_exar Messages postés 286 Date d'inscription vendredi 5 décembre 2003 Statut Membre Dernière intervention 22 avril 2012 2
22 juin 2009 à 20:42
ORIGINALCOMPO: c'est justement à cause du titre que j'avais écris le message ci-dessus... Il y est question d'"ortographe"...
Bien d'avoir corrigé ta faute, il y en a souvent de trop, ici, hélas. Heureusement, parfois, la qualité du code compense la pauvreté de l'orthographe utilisée.
Enfin, dans ce cas-ci, je suppose qu'il s'agit d'une faute de frappe non relue, donc pas vue. Dans le résumé, il n'y en a pas de trop.
FOOFYMANY: je n'ai pas testé, mais comme tu évoques le PL/SQL, je te conseille de te documenter sur le regexp_like. Très puissant.
Cela n'enlève rien à l'utilité de ton code, pour quelqu'un qui n'a pas besoin de quelque chose d'aussi poussé que cela.
Bonne continuation !
originalcompo Messages postés 65 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 octobre 2007 1
22 juin 2009 à 14:35
remplacéES (pardon pour l'orthographe)
originalcompo Messages postés 65 Date d'inscription dimanche 3 avril 2005 Statut Membre Dernière intervention 9 octobre 2007 1
22 juin 2009 à 14:34
Juste une remarque: les 36 premières lignes du "switch($ch){case '0':$mcar.='00';break; ..."
peuvent être remplacé par:

if (($ch>='0') && ($ch<='9'))
$mcar .= '0'.$ch;
elseif (($ch>='a') && ($ch<='z'))
$mcar .= ord($ch)-87;

Cordialement
foofymany Messages postés 2 Date d'inscription mardi 8 janvier 2008 Statut Membre Dernière intervention 22 juin 2009
22 juin 2009 à 11:20
Bien sur que ça fonctionne très bien. Même mieux que soundex seul. Car cette fonction à tendance à ne prendre que les consonnes. La vous avez un mix des 2 qui rend le truc assez complet et donne des résultats très cohérents.
Afficher les 10 commentaires

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.