patricktoulon
XLDnaute Barbatruc
Bonjour à tous et @Dudu2
j'ouvre cette discussion a fin de ne pas mettre le boxon dans une autre dans la quelle j'ai proposer la fonction similaire
en 2020/2021 je sais plus trop j'avais ajouté dans la fonction une partie gérant la présence de chaque mot de la chaine 1 dans la chaine 2
cela dit je me rend compte qu'elle peut être discriminatoire ou inversement me donner un 100%
alors que la chaine 2 est plus grande
certes la chaine2 contient tout les mots de la chaine 1 mais le pourcentage ne devrait pas être 100%
voici la fonction je n'en suis pas l'auteur à la base je l'ai juste arrangée a ma sauce
prenons un exemple de chaines à comparer
maintenant si je met un pluriel
je cherche le moyen donc de garder la partie unordered mais quelle soit plus juste
j'ai donc dans un fichier vierge cherché un moyen que cette partie soit plus juste au résultat
j'ai donc écrit ce nouveau code pour tester
en fait j'ai un 100% si tout les mots sont présents dans n'importe quel ordre
et j'impute une devaluation en fonction du nombre de mots supplémentaires
dites moi ce que vous en pensez
pensez vous que ce soit rentable de l'intégrer dans la fonction similaire dans a la place de la partie unordered
avec peut être un switch ressemblance/similaire
Allez @Dudu2 au boulot
je joins un fichier
j'ouvre cette discussion a fin de ne pas mettre le boxon dans une autre dans la quelle j'ai proposer la fonction similaire
en 2020/2021 je sais plus trop j'avais ajouté dans la fonction une partie gérant la présence de chaque mot de la chaine 1 dans la chaine 2
cela dit je me rend compte qu'elle peut être discriminatoire ou inversement me donner un 100%
alors que la chaine 2 est plus grande
certes la chaine2 contient tout les mots de la chaine 1 mais le pourcentage ne devrait pas être 100%
voici la fonction je n'en suis pas l'auteur à la base je l'ai juste arrangée a ma sauce
VB:
Public Function similaire(ByVal s1 As String, ByVal s2 As String) As Double
Const cFacteur As Long = &H100&, cMaxLen As Long = 256& 'Longueur maxi autorisée des chaines analysées
Dim l1 As Long, l2 As Long, c1 As Long, c2 As Long
Dim r() As Integer, rp() As Integer, rpp() As Integer, i As Integer, j As Integer
Dim c As Integer, x As Integer, y As Integer, z As Integer, f1 As Integer, f2 As Integer
Dim dls As String, ac1() As Byte, ac2() As Byte
Dim px As Double, p As Double, oz As Long
Dim t1, t2
'*****************************************************
'analyse dans un ordre different
If s1 = s2 Then similaire = 100: Exit Function
t1 = Split(Replace(s1, "-", " "), " "): t2 = Split(Replace(s1, "-", " "), " ")
If UBound(t2) > UBound(t1) Then tbl = t12: s2 = s1 Else tbl = t1
If IsArray(tbl) Then
If UBound(tbl) > 1 Then
p = 100 / (UBound(tbl) + 1)
For oz = 0 To UBound(tbl): px = px + IIf(" " & s2 & " " Like "* " & tbl(oz) & "* ", p, -p): Next
If px = 100 Then similaire = 100: Exit Function
End If
End If
'**************************************************
'analyse binaire
l1 = Len(s1): l2 = Len(s2)
If l1 > 0 And l1 <= cMaxLen And l2 > 0 And l2 <= cMaxLen Then
ac1 = s1 'conversion des chaines en tableaux de bytes
ac2 = s2
'Initialise la ligne précédente (rp) de la matrice
ReDim rp(0 To l2)
For i = 0 To l2: rp(i) = i: Next i
For i = 1 To l1
'Initialise la ligne courante de la matrice
ReDim r(0 To l2): r(0) = i
'Calcul le CharCode du caractère courant de la chaine
f1 = (i - 1) * 2: c1 = ac1(f1 + 1) * cFacteur + ac1(f1)
For j = 1 To l2
f2 = (j - 1) * 2: c2 = ac2(f2 + 1) * cFacteur + ac2(f2)
c = -(c1 <> c2) 'Cout : True = -1 => c = 1
'suppression, insertion, substitution
x = rp(j) + 1: y = r(j - 1) + 1: z = rp(j - 1) + c
If x < y Then
If x < z Then r(j) = x Else r(j) = z
Else
If y < z Then r(j) = y Else r(j) = z
End If
'transposition
If i > 1 And j > 1 And c = 1 Then
If c1 = ac2(f2 - 1) * cFacteur + ac2(f2 - 2) And c2 = ac1(f1 - 1) * cFacteur + ac1(f1 - 2) Then
If r(j) > rpp(j - 2) + c Then r(j) = rpp(j - 2) + c
End If
End If
Next j
'Reculer d'un niveau la ligne précédente (rp) et courante (r)
rpp = rp: rp = r
Next i
'Calcul la similarité via la distance entre les chaines r(l2)
If l1 >= l2 Then dls = 1 - r(l2) / l1 Else dls = 1 - r(l2) / l2
ElseIf l1 > cMaxLen Or l2 > cMaxLen Then
dls = -1 'indique un dépassement de longueur de chaine
ElseIf l1 = 0 And l2 = 0 Then
dls = 1 'cas particulier
End If
similaire = dls * 100
End Function
prenons un exemple de chaines à comparer
chaine1="titi toto"
chaine 2="titi toto"
msgbox similaire(chaine1,chaine2)
'la réponse va être sans appel c'est du 100% car on est sorti de la fonction par la partie unordered
maintenant si je met un pluriel
alors oui tout les mots de la chaine 1 se trouvent dans la chaine 2 mais elle ne sont pas egaleschaine1="titi toto"
chaine 2="titi totos"
msgbox similaire(chaine1,chaine2)
'la réponse va être sans appel c'est du 100%'car on est sorti de la fonction par la partie unordered
je cherche le moyen donc de garder la partie unordered mais quelle soit plus juste
j'ai donc dans un fichier vierge cherché un moyen que cette partie soit plus juste au résultat
j'ai donc écrit ce nouveau code pour tester
VB:
Function Ressemble(s1 As String, s2 As String)
Dim T2, T1, TbL, x, px#, devaluation#
s1 = Trim(s1): s2 = Trim(s2)
s1 = Replace(s1, "-", " ")
s2 = Replace(s2, "-", " ")
'*****************************************************
'analyse dans un ordre different(UNORDERED)
If s1 = s2 Then Ressemble = 100: Exit Function
T1 = Split(s1, " ")
T2 = Split(s2, " ")
x = WorksheetFunction.Max(UBound(T1), UBound(T2))
y = WorksheetFunction.Min(UBound(T1), UBound(T2))
devaluation = ((100 / x) * Abs(x - y)) / 2
If UBound(T2) < UBound(T1) Then TbL = T2: s2 = s1 Else TbL = T1
If IsArray(TbL) Then
If UBound(TbL) > 1 Then
p = 100 / (UBound(T1) + 1)
For oz = 0 To UBound(TbL)
If " " & s2 & " " Like "* " & TbL(oz) & " *" Then px = px + p
Next
End If
End If
'pour rendre la note equitable par rapport au nombre de mots supplémentaire
If Val(px) = 100 Then px = px - devaluation
Ressemble = px
End Function
MsgBox Ressemble("les pommes du pays de galle", "les pommes du pays de galle")
MsgBox Ressemble("les pommes du pays de galle", "les pommes vertes du pays de galle")
et j'impute une devaluation en fonction du nombre de mots supplémentaires
dites moi ce que vous en pensez
pensez vous que ce soit rentable de l'intégrer dans la fonction similaire dans a la place de la partie unordered
avec peut être un switch ressemblance/similaire
Allez @Dudu2 au boulot
je joins un fichier