J'ai essayé de créer un effet imbriqué ou récursif avec SequenceMatcher. Le but final est de comparer deux séquences, les deux pouvant contenir des instances de différents types.SequenceMatcher de Difflib - Égalité personnalisée
Par exemple, les séquences peuvent être:
l1 = [1, "Foo", "Bar", 3]
l2 = [1, "Fo", "Bak", 2]
Normalement, SequenceMatcher identifie uniquement [1] en tant que sous-séquence commune pour L1 et L2.
Je voudrais SequnceMatcher à appliquer deux fois pour les instances de chaîne, de sorte que "Foo"
et "Fo"
seront considérés comme égaux, ainsi que "Bar"
et "Bak"
, et la sous-séquence plus longue commune sera d'une longueur de 3 [1, Foo/Fo, Bar/Bak]
. C'est-à-dire, je voudrais que SequenceMatcher soit plus indulgent lors de la comparaison des membres de la chaîne.
Ce que j'ai essayé de faire est d'écrire un wrapper pour la classe intégrée str:
from difflib import SequenceMatcher
class myString:
def __init__(self, string):
self.string = string
def __hash__(self):
return hash(self.string)
def __eq__(self, other):
return SequenceMatcher(a=self.string, b=self.string).ratio() > 0.5
Edit: peut-être une façon plus élégante est:
class myString(str):
def __eq__(self, other):
return SequenceMatcher(a=self, b=other).ratio() > 0.5
En faisant cela, ce qui suit est rendu possible:
>>> Foo = myString("Foo")
>>> Fo = myString("Fo")
>>> Bar = myString("Bar")
>>> Bak = myString("Bak")
>>> l1 = [1, Foo, Bar, 3]
>>> l2 = [1, Fo, Bak, 2]
>>> SequenceMatcher(a=l1, b=l2).ratio()
0.75
Donc, évidemment, cela fonctionne, mais j'ai un mauvais pressentiment à propos de la dérogation fonction de hachage. Quand le hash est-il utilisé? Où peut-il revenir et me mordre?
états de documentation de SequenceMatcher de ce qui suit:
Ceci est une classe souple pour comparer des paires de séquences de tout type, tant que les éléments de séquence sont hashable.
Et par définition hashable éléments sont nécessaires pour satisfaire à l'exigence suivante:
objets HASHABLE qui doivent être égaux ont la même valeur de hachage.
De plus, dois-je remplacer cmp ainsi?
J'aimerais beaucoup entendre parler d'autres solutions qui me viennent à l'esprit.
Merci.
Pouvez-vous en dire plus sur l'outil de comparaison unique? N'est-ce pas exagéré de ré-implémenter l'algorithme de correspondance? – geckon
Eh bien, cela dépend de la situation et des contraintes. Si vous recherchez une égalité stricte sauf dans le cas des chaînes (ou de tous les sous-itérables?), Et que l'ordre est toujours le même, et que vous savez où commencer l'appariement ... Ou 2 de ces 3, ou autre chose. Un algo généralisé n'est pas toujours le meilleur parce que l'adapter à vos besoins peut être plus difficile que de simplement faire quelque chose de nouveau qui fait ce que vous voulez. –
Eh bien, j'ai deux séquences (disons des listes) d'objets et je veux trouver la différence entre eux. Mais pour la comparaison je ne veux utiliser aucune méthode de la classe des objets (pas même '__hash__',' __eq__', etc.) mais je veux fournir une fonction qui sera appelée avec chaque objet comme paramètre et la La valeur retournée sera utilisée pour la comparaison. Cette "fonction génératrice de clé" sera écrite par moi et pourra utiliser des méthodes de la classe des objets, des fonctions standard etc. et retournera disons une chaîne. Mais cela peut aussi être plus général (retour type). – geckon