begin process at 2010 02 10 13:55:10
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Texte

 > DISTANCE DE JARO-WINKLER

DISTANCE DE JARO-WINKLER


 Information sur la source

Note :
Aucune note
Catégorie :Texte Classé sous :Jaro, Winkler, Jaro-Winkler, distance, similarité Niveau :Débutant Date de création :29/08/2008 Date de mise à jour :29/08/2008 11:00:26 Vu :2 726

Auteur : PoulpHunter

Ecrire un message privé
Site perso
Commentaire sur cette source (14)
Ajouter un commentaire et/ou une note

 Description

La distance de Jaro-Winkler mesure la similarité entre deux chaînes de caractères.

Cette fonction permet de renvoyer la valeur de la distance de Jaro-Winkler.
Elle est normalement comprise entre 0 et 1 mais peut dépasser légèrement 1 dans le cas ou le paramètre p est modifié.
(p  est un coefficient qui permet de favoriser les chaînes avec un préfixe commun. Winkler propose pour valeur p = 0.1)

voir :
http://fr.wikipedia.org/wiki/Distance_de_Jaro-Win kler

Source

  • function JaroWinkler(prmT1, prmT2: String;p:Double=0.1): Double;
  • Var
  • ecartMax,l1,l2,compteMatching,compteTransposition,longueurPrefix,i,j:integer;
  • c1,c2,t1Matche,t2Matche:string;
  • b1,b2:array of Boolean;
  • distanceJaro:Double;
  • label endfor,exitfor2;
  • function TrouverMatches(prmTextInitial:string;b1:array of Boolean):string;
  • var
  • i:integer;
  • res:string;
  • begin
  • // Calcule le nombre de caractères qui match
  • for i := 1 to Length(prmTextInitial) do
  • begin
  • if b1[i] then//prmTextMatche[i]='_' then
  • begin
  • res:=res+prmTextInitial[i];
  • end;
  • end;
  • TrouverMatches:=res;
  • end;
  • begin
  • ecartMax:=round(Max(Length(prmT1), Length(prmT2))/2)-1;
  • if ((prmT1='') or (prmT2='')) then
  • begin
  • JaroWinkler:=0;
  • exit;
  • end;
  • compteMatching:=0;
  • compteTransposition:=0;
  • l1:=Length(prmT1);
  • l2:=Length(prmT2);
  • Setlength(b1,l1+1);
  • Setlength(b2,l2+1);
  • for i := 0 to l1 do
  • begin
  • b1[i]:=false;
  • end;
  • for i := 0 to l2 do
  • begin
  • b2[i]:=false;
  • end;
  • for i := 1 to l1 do
  • begin
  • c1:=prmT1[i];
  • if (i<=l2) then
  • c2:=prmT2[i]
  • else
  • c2:='';
  • for j := Max(i-ecartMax,1) to Min(i+ecartMax,l2) do
  • begin
  • c2:=prmT2[j];
  • if c1=c2 then //compteMatching avec transposition
  • begin
  • b1[i]:=true;
  • b2[j]:=true;
  • //Le caractère a été matché, il n'est plus disponible
  • Inc(compteMatching);
  • break;
  • end;
  • end;
  • end;
  • if (compteMatching=0) then
  • begin
  • JaroWinkler:=0;
  • exit;
  • end;
  • //Dans les caractères matchés, compte ceux qui ne matchent pas exactement
  • t1Matche:=TrouverMatches(prmT1,b1);
  • t2Matche:=TrouverMatches(prmT2,b2);
  • if t1Matche<>t2Matche then
  • begin
  • for i := 1 to length(t1Matche) do
  • begin
  • if t1Matche[i]<>t2Matche[i] then
  • Inc(compteTransposition)
  • end;
  • end else begin
  • compteTransposition:=0;
  • end;
  • distanceJaro:=1/3*((compteMatching/l1)+(compteMatching/l2)+((compteMatching-Int(compteTransposition/2))/compteMatching));
  • //Calcule la distance Winkler
  • //Calcule le prefix sur les 4 premiers car aux max
  • longueurPrefix:=0;
  • for i := 1 to min(4,min(l1,l2)) do
  • begin
  • c1:=prmT1[i];
  • c2:=prmT2[i];
  • if c1=c2 then
  • inc(longueurPrefix)
  • else
  • break;
  • end;
  • //Valeur constante définie par l'algo
  • JaroWinkler:=distanceJaro+(longueurPrefix*p*(1-distanceJaro));
  • end;
function JaroWinkler(prmT1, prmT2: String;p:Double=0.1): Double;
Var
ecartMax,l1,l2,compteMatching,compteTransposition,longueurPrefix,i,j:integer;
c1,c2,t1Matche,t2Matche:string;
b1,b2:array of Boolean;
distanceJaro:Double;
label endfor,exitfor2;
  function  TrouverMatches(prmTextInitial:string;b1:array of Boolean):string;
  var
  i:integer;
  res:string;
  begin
  // Calcule le nombre de caractères qui match
    for i := 1 to Length(prmTextInitial) do
    begin
      if b1[i] then//prmTextMatche[i]='_' then
      begin
        res:=res+prmTextInitial[i];
      end;
    end;
  TrouverMatches:=res;
  end;
begin
 ecartMax:=round(Max(Length(prmT1), Length(prmT2))/2)-1;
 if ((prmT1='') or (prmT2='')) then
 begin
  JaroWinkler:=0;
  exit;
 end;
 compteMatching:=0;
 compteTransposition:=0;
 l1:=Length(prmT1);
 l2:=Length(prmT2);
 Setlength(b1,l1+1);
 Setlength(b2,l2+1);
 for i := 0 to l1 do
 begin
  b1[i]:=false;
 end;
 for i := 0 to l2 do
 begin
  b2[i]:=false;
 end;

 for i := 1 to l1 do
 begin
  c1:=prmT1[i];
  if (i<=l2) then
    c2:=prmT2[i]
  else
    c2:='';
  for j := Max(i-ecartMax,1) to Min(i+ecartMax,l2) do
  begin
    c2:=prmT2[j];
    if c1=c2 then //compteMatching avec transposition
    begin
     b1[i]:=true;
     b2[j]:=true;
     //Le caractère a été matché, il n'est plus disponible
     Inc(compteMatching);
     break;
    end;
  end;
 end;
 if (compteMatching=0) then
 begin
  JaroWinkler:=0;
  exit;
 end;
 //Dans les caractères matchés, compte ceux qui ne matchent pas exactement
 t1Matche:=TrouverMatches(prmT1,b1);
 t2Matche:=TrouverMatches(prmT2,b2);
 if t1Matche<>t2Matche then
 begin
  for i := 1 to length(t1Matche) do
  begin
    if t1Matche[i]<>t2Matche[i] then
      Inc(compteTransposition)
  end;
 end else begin
   compteTransposition:=0;
 end;

 distanceJaro:=1/3*((compteMatching/l1)+(compteMatching/l2)+((compteMatching-Int(compteTransposition/2))/compteMatching));

 //Calcule la distance Winkler
 //Calcule le prefix sur les 4 premiers car aux max
 longueurPrefix:=0;
 for i := 1 to min(4,min(l1,l2)) do
 begin
  c1:=prmT1[i];
  c2:=prmT2[i];
  if c1=c2 then
    inc(longueurPrefix)
  else
  break;
 end;
 //Valeur constante définie par l'algo
 JaroWinkler:=distanceJaro+(longueurPrefix*p*(1-distanceJaro));
end;

 Conclusion

cette source est juste un portage delphi d'une source vb trouvée sur le net.


 Historique

29 août 2008 01:00:06 :
-
29 août 2008 01:45:44 :
Modifications proposées par John Dogget
29 août 2008 11:00:26 :
-Correction des goto en break; -Passage par array of boolean au lieu de string (un poil mieux pour la mémoire)

 Sources du même auteur

Source avec Zip Source avec une capture PATCHMAKER (GÉNÉRATION DE PATCHS : 7KO MINI NON PACKE, 15,5K...
Source avec Zip Source avec une capture BROUILLEUR DE TEXTE (CHANGE L' ORDRE DES LETTRES)
Source avec Zip Source avec une capture MSN - "CE QUE J'ÉCOUTE" ET PSEUDO ( NICKNAME ) TEXTE DÉFILAN...
Source avec Zip Source avec une capture GÉNÉRATEUR DE FICHIERS ALÉATOIRES : CLIENT DU SITE : HTTP://...

 Sources de la même categorie

Source avec Zip COMBINAISONS DE STRINGS par askil2000
Source avec Zip Source avec une capture RECONNAISSANCE DE CARACTÈRES (OCR) par Bacterius
Source avec Zip Source avec une capture NETTOYAGE AUTOMATIQUE DE NOMS DE FICHIERS par John Dogget
Source avec Zip BASE DE DONNÉE WIKI par thithony
Source avec Zip Source avec une capture DICO ET AIDE MOTS CROISÉE par thithony

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture SUPERVISEUR VNC par moldov
Source avec Zip DISTANCE LEVENSHTEIN (DISTANCE ENTRE DEUX CHAINES) par DevNul
Source avec Zip FBPDM LOGICIEL DE PRISE DE MAIN À DISTANCE par fbalien
Source avec Zip Source avec une capture COMPARAISON "INTELLIGENTE" ET MOTEUR DE RECHERCHE par Forman
Source avec Zip Source avec une capture CALCUL DE DISTANCE À PARTIR DES COORDONNÉES par philippe54250

Commentaires et avis

Commentaire de John Dogget le 29/08/2008 01:14:06

Lu.

Quand tu n'as qu'une instruction après un "if", tu peux te passer d'un bloc "begin-end".

Exemple l38 à 46, tu as écrit :
if (i<=l2) then
begin
c2:=t2[i];
end else begin
c2:='';
end; "

Ca se remplace avantageusement par :
if i<=12 then
c2:=t2[i]
else
c2:='';

Le code y gagne beaucoup en lisibilité ...
Sinon, je regarderai dans les details plus tard, ça m'as l'air un poil compliqué pour cette jeure tardive :)

Commentaire de blueperfect le 29/08/2008 04:32:23

C comme un SoundEx ?

Commentaire de Loda le 29/08/2008 09:18:25

salut,

tu peux remplacer les "goto endForX" par un "break", plus propre.

sinon ça m'a l'air intéressant, je regarderais ça plus en détails une autres fois.

aussi, je me demandais dans quelle mesures le strings avec des '_' vont poser problèmes...

a+

Commentaire de PoulpHunter le 29/08/2008 11:36:35

Pour blueperfect : alors SoundEx est basé sur la phonétique, ici on veux juste savoir le % de ressemblance avec un autre mot (point de vue des lettres) pour la correction orthographique via dictionnaire par exemple.
SoundEx ne prend en compte que la ressemblance de prononciation.

Pour loda : alors sa y est j'ai remplacé les goto par des break, et sinon normalement le '_' ne devais pas poser de problème vu que la string n'étais pas réellement utile...
j'ai remplacé par un tableau de boolean ce qui fait le même boulot, pour moins de mémoire...

Commentaire de Bacterius le 29/08/2008 12:11:10

John Dogget tu es le spécialiste des blocs begin-end ;)

Cordialement, Bacterius !

Commentaire de cantador le 29/08/2008 12:27:09

Bonjour,
Intéressant..
ce code pourrait être utilisé par CS afin d'offrir une possibilité de recherche à l'intérieur de ses propres commentaires sur le forum.
A voir..

Commentaire de Loda le 29/08/2008 13:56:26

re,

par curiosité: Tu utilises cet algo pour quel type d'application ? D'après l'article de wikipedia, son usage semble limité à des mots ou des textes très courts. Et même dans ce cas, un couple de mots assez différent semblent retourner des valeurs similaire à un couple de mots assez semblable. (je dis "semble", car je ne pas fait de test)

je m'intéresse au sujet pour un projet d'alogmerateur de news. Afin de détecter les news à double (typiquement avec une virgule en plus ou un titre un peu plus court)

bon week-end,

Commentaire de PoulpHunter le 29/08/2008 14:50:22

Sa dépend ce que l'on entend par similaire.
Cet algo renvoi :
algo(MARTHA,MARHTA)=0.96
algo(DWAYNE,DUANE)=0.84
algo(DIXON,DICKSONX)=0.81

J'ai utilisé cet algo avec la source :
http://www.delphifr.com/codes/COMPARAISON-INTELLIGENTE-MOTEUR-RECHERCHE_39168.aspx

cela m' a donné des colonnes du style :
http://poulphunter1.free.fr/mot.jpg

pour ce qui est de gros texte, je ne sais pas ce que sa donne, mais sinon il doit être assez facile de porter cette source à des streams ou autre... (au lieu de strings : array of byte)

PS: c'est possible que je n'ai plus le net pour un ptit moment à partir de demain, au cas dsl de pas répondre de suite...

Commentaire de blueperfect le 29/08/2008 18:04:04

Tu as un exemple ?

Pour soundex :

En effectuant cet algorithme, on obtient avec "Robert" et "Rupert" la même chaîne : "R163", tandis que "Rubin" donne "R150".

Commentaire de PoulpHunter le 30/08/2008 00:20:23

Alors si on prend pour
A : la distance de Levenstein / Longeur max des 2 mots
B : la distance de Jaro
C : la distance de Jaro-Winkler
cela donne le tableau suivant :

Robert - Rupert
A=66.67%
B=77.78%
C=80%

Robert - Rubin
A=33.33%
B=57.78%
C=62%

Rupert - Rubin
A=33.33%
B=57.78%
C=66.22%

on constate que Robert ressemble plus à Rupert que Rubin (via tout les algos)
après on peut même dire via Jaro-Winkler que Rubin ressemble plus à Rupert qu'à Robert
mais sa c'est surtout parce que Winkler à rajouté le fait que le préfixe est plus important.

Commentaire de blueperfect le 30/08/2008 01:23:01

En fait, comparé à SoundEx, il paraît plus international ton algo !

Les accents, tu gais comment ?

Pour SoundEx, il y a une correspondance spéciale...

http://fr.wikipedia.org/wiki/Soundex

Commentaire de Loda le 31/08/2008 18:24:54

merci pour la comparaison. Cela éclaire bien ma lanterne....

a+

Commentaire de PoulpHunter le 02/09/2008 17:06:05

Ben pour les accents l'algo considère pareil une lettre accentuée qu'une autre lettre.
Pour y remédier on pourrais y incorporer juste avant un algo qui supprime les accents avant comparaison par exemple.

Et au faite pour Loda, si tu veux utiliser cet algo dans ton aglomérateur de news, ne te sert pas du côté Winkler (car sa compte plus le préfixe)
Utilise juste la distance de Jaro.

Commentaire de blueperfect le 02/09/2008 17:27:25

Je me demande ce que cela donnerait en utilisant un algorythme de comparaison de bitmap !

Tu dessines la chaine sur un canvas, et tu fais la difference avec un bitma p rempli selon un pourcentage ....???

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Actionner et arrêter une application sur un poste à distance [ par thierry ] SalutMeme question j'ai essaye ICS sous CBUILDER avec l'exemple de Chat donné .Mon programme compare la chaine recu au nom du programmeà lancer sur le Faire executer une appli a distance [ par slhuilli ] Quelu'un saurait il s'il est possible a partir d'un poste (PC1) de faire executer et de terminer une tache sur un autre poste (PC2), sachant que ces d problemes de timer et ntmstrm [ par crogger ] Bonjour, je fais de la capture d ecran que je convertit en jpg, et que je transmet en stream avec le composant NMSTRM de fastnet pour recuperer a dist Assistance a distance [ par SlunBreak ] Bonjours, Je cherche le moyen d'inserer une fonction d'assistance à distance sur un programme utilisant les composants ClientSocket et ServerSocket. L Compiler à distance [ par FleX2009 ] Bonjour, j'aurai besoin de compiler &#224; distance une DLL Delphi, c'est-&#224;-dire faire une application qui compile automatiquement du code Delphi Verifier le lancement d'un service à distance [ par abdouinf ] Bonjour &#224; tous,je suis en train de developper une application Client/Serveur avec TSocketConnection, j'ai un service qui tourne sur le serveur po controle d'un pc à distance [ par templeofboom ] bonjour je suis d&#233;butant en delphi et j'aimerais savoir si l'on peu peu prendre le controle d'une machine &#224; distance lorsqu'on connait son a acces a distance [ par exyacc ] salut, je voudrais que mon prog delphi ajoute un acces a distance ds les connexions reseau avec un num de tel, login et pass.&nbsp; en fait , c'est p projet controle a distance [ par bts_informatique ] bonjour a tous je sius etudiant et jai un projet de fin d'etude j'ai cree une connection entre deux poste et mon probleme que cette connection&nbsp; e a 900 kms de distance y a t il moyen de redemarrer un pc ? [ par patviro ]


Nos sponsors


Sondage...

Comparez les prix

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,936 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales