2010-09-22 2 views
1

J'ai 2 listes de dictonaries et je veux retourner des articles qui ont le même id mais un titre différent. à savoirPython comparer des dictons pour différentes valeurs

list1 = [{'id': 1, 'title': 'title1'}, {'id': 2, 'title': 'title2'}, {'id': 3, 'title': 'title3'}] 

list2 = [{'id': 1, 'title': 'title1'}, {'id': 2, 'title': 'title3'}, {'id': 3, 'title': 'title4'}] 

J'y retournerais [{'id': 2, 'title': 'title2'}, {'id': 3, 'title': 'title3'}] que les titres sont différents liste2 à list1.

+0

Vouliez-vous dire, 'title': 'titre1'? – marr75

+0

oui. merci, il devrait être changé maintenant – John

Répondre

2

Je propose que vous refactoring votre conception de ne pas être une liste de dictionnaires, mais 2 dictionnaires de id: paires titre. L'algorithme est trivial à ce moment-là et la performance est meilleure.

Exemple de code (modifié pour refléter l'affirmation correcte de SilentGhost):

titles1 = {1: "title1", 2: "title2", 3: "title3"} 
titles2 = {1: "title1", 2: "not_title2", 3: "title3"} 
for id, title in titles1.iteritems(): 
    # verify the key is in titles2, compare title to titles2[id] 

Exemple de code pour convertir la liste de dictionnaire pour le dictionnaire avec id comme la clé:

titles1 = dict([(x["id"], x) for x in list1]) 
+0

Merci pour le conseil. Je suis nouveau sur Python alors pourriez-vous me dire comment je peux convertir ma liste de dictionnaires dictionnaires de id: paires de titres? Merci – John

+0

Je voudrais noter que cela fonctionnerait pour des objets plus complexes que juste une chaîne comme les valeurs dans chaque dictionnaire. De plus, si vous n'entendez pas d'effets secondaires sur l'un ou l'autre dictionnaire dans votre boucle de vérification, vous pouvez créer une nouvelle liste d'objets incompatibles en utilisant un style fonctionnel, je le recommande. – marr75

+0

il n'y a pas besoin de '.keys()' – SilentGhost

0

Différents dictionnaires sont égaux si leur contenu est égal. Alors vous pouvez juste faire:

for i in list1: 
    if i not in list2: 
     result.append(i) 
+0

Gardez juste à l'esprit que la recherche 'if i not in list2' s'exécute en temps linéaire, donc cela devient cher quand' list2' est grand. Lorsque des recherches répétées sont nécessaires, pensez toujours à utiliser un dictionnaire ou un ensemble. Puisque les dictionnaires ne peuvent pas être hachés, vous ne pouvez pas simplement mettre 'list2' dans un ensemble, mais la réponse de marr75 montre comment vous pouvez contourner cela. – gotgenes

1
[dc for dc in list1 if dc['id'] in [d["id"] for d in list2] and dc not in list2] 
+0

Cela échelles mal. Pour un, vous avez une boucle interne ('[[[id"] pour d dans list2] ') qui s'exécute pour chaque itération de la boucle externe (' dc for dc in list1'). Vous devriez avoir au moins mis en cache cette liste de boucles internes. Deuxièmement, la recherche de liste est linéaire, alors que la recherche par dictionnaire ou par ensemble est amortie en temps constant. La réponse de marr75 est sur la bonne voie. – gotgenes

+0

S'il s'inquiète de la mise à l'échelle, il devrait vraiment repenser toute la structure. Je viens de signaler une solution qui fonctionne avec sa structure de données actuelle. – dekomote

0

Si vous refactorisons votre structure de données (en supposant que id est unique dans un dictionnaire), une comparaison pourrait être mise en œuvre plus efficacement (à savoir dans O(n). réf O(1). Exemple:

#!/usr/bin/env python 

d1 = { 
    1 : {"title" : "title1"}, 
    2 : {"title" : "title2"}, 
    3 : {"title" : "title3"}, 
} 

d2 = { 
    1 : {"title" : "title1"}, 
    2 : {"title" : "title3"}, 
    3 : {"title" : "title4"}, 
} 

for key, value in d1.items(): 
    if not value == d2[key]: 
     print "@", key, "values differ:", d1[key], "vs", d2[key] 

# @ 2 values differ: {'title': 'title2'} vs {'title': 'title3'} 
# @ 3 values differ: {'title': 'title3'} vs {'title': 'title4'} 

ou moins:

print [ (k, (d1[k], d2[k])) for k in d1 if not d2[k] == d1[k] ] 
# [(2, ({'title': 'title2'}, {'title': 'title3'})), \ 
# (3, ({'title': 'title3'}, {'title': 'title4'}))] 
Questions connexes