Formule pour trouver des matchs «parfait»

J'ai une liste de + -8000 éléments qui est le résultat après l'application de nombreuses techniques pour supprimer les doublons (la liste a débuté à plus de 10000 éléments).

J'ai maintenant le problème suivant:

Exemple 1. Jack Daniel 2. Jack Daniels 3. Jack Daniel's

De toute évidence, tout ce qui précède se rapporte à un élément, mais ils sont encore techniquement exclusifs. J'ai essayé de tirer les premières 4 lettres et de vérifier les matchs, mais il y avait + -4000 et la plupart d'entre eux étaient des faux positifs, c'est-à-dire

  1. Jack Dxxx
  2. Jack Bxxx

Les deux tireraient Jack mais ne serait pas un duplicata valable.

Des pensées?

Basé sur le commentaire de Zoredache, voici mon exemple de classeur en utilisant VBA et la distance Levenshtein pour trouver des chaînes similaires dans une grande liste. Il est basé sur @smirkingman et @ Apostolos55 réponses sur stackoverflow .

La distance de Levenshtein entre deux mots est le nombre minimal de modifications de caractères individuels (insertion, suppression, substitution) nécessaires pour changer un mot dans l'autre

J'ai implémenté deux versions différentes. Vérifiez quelle fonction est plus rapide pour votre cas avec 8000 valeurs. Si vous êtes curieux, consultez le code VBA complet sur Github . Augmenter le seuil dans la ligne const treshold = 1 si vous voulez des résultats avec plus de 1 modification requise pour obtenir une correspondance quelque part.

Entrez la description de l'image ici

  • Syntaxe de formule: =LevenshteinCompare( <cell_to_check> , <range_to_search_in> )
    Exemple: =LevenshteinCompare(A2;A$2:A$12) (Notez la plage fixe)
  • Syntaxe de sortie: <number_of_required_edits> - [<match_address>] <match_value>

 Private Function Levenshtein(S1 As String, S2 As String) Dim i As Integer, j As Integer Dim l1 As Integer, l2 As Integer Dim d() As Integer Dim min1 As Integer, min2 As Integer l1 = Len(S1) l2 = Len(S2) ReDim d(l1, l2) For i = 0 To l1 d(i, 0) = i Next For j = 0 To l2 d(0, j) = j Next For i = 1 To l1 For j = 1 To l2 If Mid(S1, i, 1) = Mid(S2, j, 1) Then d(i, j) = d(i - 1, j - 1) Else min1 = d(i - 1, j) + 1 min2 = d(i, j - 1) + 1 If min2 < min1 Then min1 = min2 End If min2 = d(i - 1, j - 1) + 1 If min2 < min1 Then min1 = min2 End If d(i, j) = min1 End If Next Next Levenshtein = d(l1, l2) End Function Public Function LevenshteinCompare(S1 As Range, wordrange As Range) Const treshold = 1 For Each S2 In Application.Intersect(wordrange, wordrange.Parent.UsedRange) oldRes = newRes newRes = Levenshtein(S1.Value, S2.Value) If oldRes < newRes And oldRes <> "" Or S1.Address = S2.Address Then newRes = oldRes newS2row = oldS2row Else oldS2 = S2 oldS2row = S2.Address(0, 0) End If newS2 = oldS2 Next If newRes <= treshold Then LevenshteinCompare = newRes & " - [" & newS2row & "] " & newS2 Else LevenshteinCompare = "" End If End Function 

C'était amusant ☜ (゚ ヮ ゚ ☜)

Utilisez = len et si la différence est inférieure à 2, marquer le plus possible

Et quelque chose comme = mid (Value, (len_Value – 7), 4) le marquer comme possilbe dupe.

Combiné avec ce que vous avez déjà, vous devriez avoir un ensemble beaucoup plus faisable pour travailler.

modifier

Formules comme celle-ci, Notez que "Jack Daniel" <> "Jack Berries" dans G2. Mais ressemble à une éventuelle correspondance partout ailleurs. Vous devriez modifier un peu pour répondre à vos besoins spécifiques, mais il devrait arriver à un nombre gérable.

C1 = IF (GAUCHE (A1,4) = GAUCHE (B1,4), "T", "F")

D1 = IF (LEN (A1) – LEN (B1) <= 2, "T", "F")

E1 = LEN (A1)

F1 = LEN (B1)

G1 = IF (MID (A1, (E1 – 7), 4) = MID (B1, (E1 – 7), 4), "T", "F")

Entrez la description de l'image ici