2016-03-30 1 views
-1

Je parcours deux instances de la même classe afin de vérifier l'égalité. Ces deux instances de cette classe sont créées par différents moyens: l'un à partir d'un pickle, et l'autre à partir d'un document json.Trier les deux éléments d'un tuple, en ignorant le cas, dans une liste, de sorte que les clés d'un dictionnaire s'alignent correctement

Je parcours les propriétés de ces objets pour vérifier l'égalité, mais les clés des dictionnaires ne sont pas toujours alignées, donc elles ne peuvent pas être comparées correctement. J'ai donc essayé de trier ces tuples, mais je ne peux pas toujours obtenir la même clé de ces deux objets en raison de la casse.

Une tentative me donne le côté gauche triés:

def __eq__(self, other): 
    for (self_key, other_key) in sorted(
     zip(self.__dict__, other.__dict__), 
     key=lambda element: (element[0].lower(), element[1].lower())):    
      print self_key, " ", other_key 
     .... 

qui sort

alpha VAR_THRESH 
chunksize VAR_MAXITER 
decay decay 
.... 

Et si je fais explicitement que le côté droit lower() je reçois le contraire: par exemple

.... 
    key=lambda element: (element[0], element[1].lower())): 
    .... 

Le côté gauche n'est pas trié par le bas.

VAR_MAXITER alpha 
VAR_THRESH chunksize 
alpha VAR_THRESH 
chunksize VAR_MAXITER 
decay decay 

Si je laisse le .lower() sur les deux éléments, je reçois le second exemple. Comment puis-je m'assurer que les bonnes clés sont toujours alignées? Ou en d'autres termes, comment puis-je trier par les deux valeurs dans les tuples, en ignorant le cas, de sorte qu'ils s'alignent toujours?

+0

Ordre est hors de propos, si les dicts ont-ils compareront les mêmes objets égaux –

Répondre

2

zip() vous donnera les éléments correspondants dans chaque itérable que vous lui donnez. Trier ce que zip() retours ne vous aidera pas. Vous devez trier les clés avant de les transmettre à zip(). Ce n'est vraiment pas ce que vous voulez, cependant. Il suffit de faire ceci:

def __eq__(self, other): 
    if self.__dict__.viewkeys() != other_keys.__dict__.viewkeys(): # .keys() in Python 3 
     return False 
    return all(other.__dict__[key] == self.__dict__[key] for key in self.__dict__) 

La façon facile serait ceci:

def __eq__(self, other): 
    self.__dict__ == other.__dict__ 

mais le premier, vous pouvez plus facilement changer de définir ce qui compte comme équivalent.

qui suit (proposé par Padraic Cunningham) est plus proche de ce que vous voulez:

def __eq__(self, other): 
    return all(
     sorted(v) == sorted(self.__dict__[key]) 
      if isinstance(v, np.array) 
     else self.__dict__[key] == v 
     for key, v in other.__dict__.iteritems() 
    ) 

C'est un raccourci pour cela:

def __eq__(self, other): 
    for key, v in other.__dict__.iteritems(): # .items() in Python 3 
     if isinstance(v, np.array) and sorted(v) != sorted(self.__dict__[key]): 
       return False 
     elif self.__dict__[key] != v: 
      return False 
    return True 
+0

je dois parcourir les clés du dict parce que l'une des valeurs est un tableau de np. Votre réponse avant l'édition m'a aidé à arriver à la bonne réponse, si vous revenez en arrière, je vais accepter. – nook

+0

@nook: Okay; J'ai reculé. – zondo

+0

'si d2.keys()! = D1.keys()' est suffisant, ou 'si d2.viewkeys()! = D1, viewkeys()' pour python2, pas besoin de faire des ensembles –

-1

Les dictionnaires sont par nature non ordonnée. Contraindre les clés dans un certain ordre qui correspond à votre définition particulière est certainement possible, mais aussi entièrement inutile. Vous pourriez plutôt essayer quelque chose comme ceci:

def __eq__(self, other): 

    # first, check to make sure that the two sets of keys are identical 
    if self.__dict__.keys() != other.__dict__.keys(): 
    return False 

    # now that we know the dictionaries have identical key sets, check 
    # for equality of values. 
    for key in self.__dict__.keys(): 
    if self.__dict__[key] != other.__dict__[key]: 
     return False 

    # if everything worked, then the dictionaries are identical! 
    return True