2010-11-12 16 views
12

J'ai une liste d'objets et j'ai une table db pleine d'enregistrements. Ma liste d'objets a un attribut de titre et je veux supprimer tous les objets avec des titres en double de la liste (en laissant l'original).Supprimer les doublons dans la liste d'objets avec Python

Ensuite, je veux vérifier si ma liste d'objets a des doublons d'enregistrements dans la base de données et si c'est le cas, supprimez ces éléments de la liste avant de les ajouter à la base de données.

J'ai vu des solutions pour supprimer les doublons d'une liste comme celle-ci: myList = list(set(myList)), mais je ne suis pas sûr de savoir comment faire cela avec une liste d'objets?

Je dois aussi maintenir l'ordre de ma liste d'objets. Je pensais aussi peut-être que je pourrais utiliser difflib pour vérifier les différences dans les titres.

+4

Étape 1. Recherche. Cette formulation exacte est utilisée chaque semestre dans la classe de programmation Python. S'il vous plaît chercher. –

+0

__en sortant l'original__, qu'est-ce que cela signifie? car si, comme vous l'avez dit, vous voulez __ maintenir l'ordre__ de la liste, la première occurrence d'un objet dupliqué dans la liste sera le droit d'origine? – mouad

+0

oui, je voulais juste dire que je veux supprimer tous les doublons, sauf pour l'original. @ S.Lott, j'ai cherché une tonne et je n'ai rien trouvé, c'est pourquoi je suis venu ici. Pouvez-vous citer un exemple qui aborde ce problème précis? Je serais heureux de le voir. – imns

Répondre

28

Le set(list_of_objects) ne supprime les doublons si vous savez ce qu'est un double est, qui est, vous aurez besoin de définir une unicité d'un objet.

Afin de faire cela, vous devrez rendre l'objet lavable. Vous devez définir à la fois la méthode __hash__ et __eq__, voici comment:

http://docs.python.org/glossary.html#term-hashable

Bien que, vous aurez probablement besoin de définir la méthode __eq__.

EDIT: Comment mettre en œuvre la méthode __eq__:

Vous aurez besoin de savoir, comme je l'ai mentionné, la définition unique de votre objet. Supposé que nous avons un livre avec les attributs author_name et le titre que leur combinaison est unique, (donc, nous pouvons avoir beaucoup de livres Stephen King écrit, et de nombreux livres nommés The Shining, mais seulement un livre nommé The Shining par Stephen King), puis la mise en œuvre est comme suit:

def __eq__(self, other): 
    return self.author_name==other.author_name\ 
      and self.title==other.title 

de même, voilà comment je parfois mettre en œuvre la méthode __hash__:

def __hash__(self): 
    return hash(('title', self.title, 
       'author_name', self.author_name)) 

vous pouvez vérifier que si vous créez une liste de 2 livres de même auteur et le titre, le livre les objets seront être le même (avec opérateur is) et égal (avec l'opérateur ==). En outre, quand set() est utilisé, il enlèvera un livre.

EDIT: C'est une ancienne anwser de moi, mais je ne remarque maintenant qu'il a l'erreur qui est corrigée avec biffés dans le dernier paragraphe: objets avec le même hash() ne donnera pas True par rapport à is . La Hashabilité de l'objet est cependant utilisée si vous avez l'intention de les utiliser en tant qu'éléments d'un ensemble, ou en tant que clés dans un dictionnaire.

+0

Bien, je ne connaissais pas '__hash__' et' __eq__'. Des exemples sur la façon d'implémenter '__eq__'? – imns

+0

voir la modification ci-dessus – vonPetrushev

6

Puisqu'ils ne sont pas traitables, vous ne pouvez pas utiliser un ensemble directement. Les titres devraient être bien.

Voici la première partie.

seen_titles = set() 
new_list = [] 
for obj in myList: 
    if obj.title not in seen_titles: 
     new_list.append(obj) 
     seen_titles.add(obj.title) 

Vous allez devoir décrire quelle base de données/ORM etc. vous utilisez pour la deuxième partie.

+0

J'utilise mysql avec sqlobject. – imns

+0

@bababa veuillez mettre à jour la question afin que les autres personnes la voient aussi. – aaronasterling

+0

@bababa, je ne vois pas un bon moyen de le faire en utilisant sqlobject (c'est-à-dire sans extraire tous les objets de la DB dans une requête ou faire une requête par objet) donc je vais attendre un peu ne sait pas sqlobject mieux que je ne viens pas. – aaronasterling

1

Cela semble assez minime:

new_dict = dict() 
for obj in myList: 
    if obj.title not in new_dict: 
     new_dict[obj.title] = obj 
0

Ses freinds assez facile: -

a = [5,6,7,32,32,32,32,32,32,32,32]

une = liste (ensemble (a))

impression (a)

[5,6,7,32] 

c'est tout! :)

+5

Impossible de faire cela sur une liste contenant des objets. –

0

Si vous souhaitez conserver l'ordre initial utiliser:

seen = {} 
new_list = [seen.setdefault(x, x) for x in my_list if x not in seen] 

Si vous ne se soucient pas de commander, utilisez-le:

new_list = list(set(my_list))