Je recherche un algorithme de similarité de chaîne qui donne de meilleurs résultats sur des chaînes de longueur variable que ceux qui sont généralement suggérés (distance de levenshtein, soundex, etc.).
Par exemple,
Donnée la chaîne A: "Robert",
Puis chaîne B: "Amy Robertson"
serait un meilleur match que
Chaîne C: "Richard"
En outre, de préférence, cet algorithme doit être indépendant de la langue (fonctionne également dans des langues autres que l'anglais).
Réponses:
Simon White de Catalysoft a écrit un article sur un algorithme très intelligent qui compare des paires de caractères adjacentes qui fonctionne très bien pour mes besoins:
http://www.catalysoft.com/articles/StrikeAMatch.html
Simon a une version Java de l'algorithme et ci-dessous, j'en ai écrit une version PL / Ruby (tirée de la version ruby simple faite dans le commentaire d'entrée du forum associé par Mark Wong-VanHaren) afin que je puisse l'utiliser dans mes requêtes PostgreSQL:
Fonctionne comme un charme!
la source
string_similarity("vitamin B", "vitamin C") #=> 1
y a-t-il un moyen simple d'empêcher ce genre de comportement?La réponse de marzagao est excellente. Je l'ai converti en C # alors j'ai pensé le poster ici:
Lien Pastebin
la source
(2.0 * intersection) / union
- j'obtiens Double.NaN en comparant deux chaînes vides.Voici une autre version de la réponse de marzagao , celle-ci écrite en Python:
la source
Voici mon implémentation PHP de l'algorithme StrikeAMatch suggéré, par Simon White. les avantages (comme indiqué dans le lien) sont:
Un vrai reflet de la similitude lexicale - les chaînes avec de petites différences doivent être reconnues comme étant similaires. En particulier, un chevauchement important de sous-chaînes doit indiquer un niveau élevé de similitude entre les chaînes.
Une robustesse aux changements d'ordre des mots - deux chaînes qui contiennent les mêmes mots, mais dans un ordre différent, doivent être reconnues comme étant similaires. D'un autre côté, si une chaîne n'est qu'un anagramme aléatoire des caractères contenus dans l'autre, alors elle devrait (généralement) être reconnue comme différente.
Indépendance linguistique - l'algorithme devrait fonctionner non seulement en anglais, mais dans de nombreuses langues différentes.
la source
Une version plus courte de la réponse de John Rutledge :
la source
intersection
variable est un gaspillage de ligne.Cette discussion a été vraiment utile, merci. J'ai converti l'algorithme en VBA pour une utilisation avec Excel et j'ai écrit quelques versions d'une fonction de feuille de calcul, l'une pour une simple comparaison d'une paire de chaînes, l'autre pour comparer une chaîne à une plage / un tableau de chaînes. La version strSimLookup renvoie la dernière meilleure correspondance sous forme de chaîne, d'index de tableau ou de métrique de similarité.
Cette implémentation produit les mêmes résultats que ceux répertoriés dans l'exemple Amazon sur le site Web de Simon White, à quelques exceptions près sur les matchs à faible score; Je ne sais pas où la différence s'insinue, pourrait être la fonction Split de VBA, mais je n'ai pas enquêté car cela fonctionne bien pour mes besoins.
la source
Je suis désolé, la réponse n'a pas été inventée par l'auteur. Il s'agit d'un algorithme bien connu qui a été présenté pour la première fois par Digital Equipment Corporation et est souvent appelé shingling.
http://www.hpl.hp.com/techreports/Compaq-DEC/SRC-TN-1997-015.pdf
la source
J'ai traduit l'algorithme de Simon White en PL / pgSQL. C'est ma contribution.
la source
Les métriques de similarité de chaînes contiennent un aperçu de nombreuses métriques différentes utilisées dans la comparaison de chaînes ( Wikipedia a également une vue d'ensemble). Une grande partie de ces métriques est implémentée dans une bibliothèque simmetrics .
Encore un autre exemple de métrique, non inclus dans l'aperçu donné est par exemple la distance de compression (en essayant d'approcher la complexité de Kolmogorov ), qui peut être utilisée pour des textes un peu plus longs que celui que vous avez présenté.
Vous pourriez également envisager d'examiner un sujet beaucoup plus large du traitement du langage naturel . Ces packages R peuvent vous aider à démarrer rapidement (ou au moins vous donner des idées).
Et une dernière modification - recherchez les autres questions sur ce sujet à SO, il y en a pas mal de connexes.
la source
Une version PHP plus rapide de l'algorithme:
Pour les données que j'avais (environ 2300 comparaisons), j'ai eu un temps de fonctionnement de 0,58sec avec la solution Igal Alkon contre 0,35sec avec le mien.
la source
Une version dans la belle Scala:
la source
Voici la version R:
la source
Publier la réponse de Marzagao dans C99, inspirée de ces algorithmes
Quelques tests basés sur l' article original :
la source
En s'appuyant sur l'impressionnante version C # de Michael La Voie, conformément à la demande d'en faire une méthode d'extension, voici ce que j'ai trouvé. Le principal avantage de le faire de cette façon est que vous pouvez trier une liste générique en fonction du pourcentage de correspondance. Par exemple, considérez que vous avez un champ de chaîne nommé "Ville" dans votre objet. Un utilisateur recherche «Chester» et vous souhaitez renvoyer les résultats par ordre décroissant de correspondance. Par exemple, vous voulez que les correspondances littérales de Chester apparaissent avant Rochester. Pour ce faire, ajoutez deux nouvelles propriétés à votre objet:
Ensuite, sur chaque objet, définissez SearchText sur ce que l'utilisateur a recherché. Ensuite, vous pouvez le trier facilement avec quelque chose comme:
Voici la légère modification pour en faire une méthode d'extension:
la source
Mon implémentation JavaScript prend une chaîne ou un tableau de chaînes, et un plancher facultatif (le plancher par défaut est 0,5). Si vous lui passez une chaîne, elle retournera vrai ou faux selon que le score de similarité de la chaîne est supérieur ou égal au plancher. Si vous lui passez un tableau de chaînes, il renverra un tableau de ces chaînes dont le score de similarité est supérieur ou égal au plancher, triées par score.
Exemples:
C'est ici:
la source
for(var j = 0; j < pairs1.length; j++){
devrait êtrefor(var j = 0; j < pairs2.length; j++){
L'algorithme de coefficient de Dice (réponse de Simon White / marzagao) est implémenté dans Ruby dans la méthode pair_distance_similar dans le gem amatch
https://github.com/flori/amatch
Ce joyau contient également des implémentations d'un certain nombre d'algorithmes d'appariement approximatif et de comparaison de chaînes: distance d'édition de Levenshtein, distance d'édition des vendeurs, distance de Hamming, la plus longue longueur de sous-séquence commune, la plus longue longueur de sous-chaîne commune, la métrique de distance de paire, la métrique Jaro-Winkler .
la source
Une version Haskell - n'hésitez pas à suggérer des modifications car je n'ai pas beaucoup fait Haskell.
la source
Clojure:
la source
Qu'en est-il de la distance de Levenshtein, divisée par la longueur de la première chaîne (ou encore divisée par la longueur min / max / moyenne des deux chaînes)? Cela a fonctionné pour moi jusqu'à présent.
la source
Hé les gars, j'ai essayé cela en javascript, mais je suis nouveau, quelqu'un connaît des moyens plus rapides de le faire?
la source
x
ety
, et vous ne devez pas parcourir les boucles en utilisant unefor..in..
boucle (utilisezfor(..;..;..)
plutôt).Voici une autre version de Similarity basée sur l'indice Sørensen – Dice (réponse de marzagao), celle-ci écrite en C ++ 11:
la source
Je cherchais une implémentation pure ruby de l'algorithme indiqué par la réponse de @ marzagao. Malheureusement, le lien indiqué par @marzagao est rompu. En réponse @ s01ipsist, il a indiqué bijou rubis amatch où la mise en œuvre n'est pas pur rubis. J'ai donc cherché un peu et trouvé gem fuzzy_match qui a une implémentation ruby pure (bien que cette gemme l'utilise
amatch
) ici . J'espère que cela aidera quelqu'un comme moi.la source