2010-03-05 6 views
15

J'ai deux listes dont la longueur est garantie. Je veux comparer les valeurs correspondantes dans la liste (sauf le premier élément) et imprimer celles qui ne correspondent pas. La façon dont je le fais est comme çaFaçon pythonienne de comparer deux listes et d'imprimer les différences

i = len(list1) 
if i == 1: 
    print 'Nothing to compare' 
else: 
    for i in range(i): 
     if not (i == 0): 
      if list1[i] != list2[i]: 
       print list1[i] 
       print list2[i] 

Y a-t-il une meilleure façon de le faire? (Python 2.x)

+2

Programmation fonctionnelle à la sauvetage: regardez dans la carte et zip! – mjv

Répondre

20
list1=[1,2,3,4] 
list2=[1,5,3,4] 
print [(i,j) for i,j in zip(list1,list2) if i!=j] 

sortie:

[(2, 5)] 

Edit: facilement étendu pour sauter n premiers éléments (même sortie):

list1=[1,2,3,4] 
list2=[2,5,3,4] 
print [(i,j) for i,j in zip(list1,list2)[1:] if i!=j] 
+0

tuple déballage serait plus rapide que l'indexation. également tranchage ne fonctionnerait pas dans py3k – SilentGhost

+0

supprimé l'indexation, mieux? :) – Mizipzor

+1

Exactement ce que je cherchais. Merci – randomThought

2

edit: oups, n'a pas vu le "ignorer premier élément" partie

from itertools import islice,izip 

for a,b in islice(izip(list1,list2),1,None): 
    if a != b: 
     print a, b 
2

Il y a une classe agréable appelée difflib.SequenceMatcher dans la bibliothèque standard pour cela.

+0

Je comprends comment vous utiliseriez ceci pour trouver des blocs correspondants, mais pas des éléments qui sont différents. Ou est-ce que je manque quelque chose? – RyanWilcox

+0

@RyanWilcox: cela devrait être facile dans O (n) une fois que vous avez les blocs correspondants –

2

Constatant l'exigence de sauter la première ligne:

from itertools import izip 
both = izip(list1,list2) 
both.next() #skip the first 
for p in (p for p in both if p[0]!=p[1]): 
    print pair 
  1. Ceci utilise izip, une version d'itérateur (itertools) de zip, pour générer un itérateur à travers des paires de valeurs. De cette façon, vous n'utilisez pas une charge de mémoire générant une liste compressée complète.
  2. Il exécute l'itérateur both de un pour éviter le traitement du premier élément et pour éviter d'avoir à effectuer la comparaison d'index à chaque étape de la boucle. Cela le rend aussi plus propre à lire.
  3. Enfin, il parcourt chaque ligne renvoyée par un générateur qui ne donne que des paires inégales.
5

Personne ne dit filtre:

a = [1, 2, 3] 
b = [42, 3, 4] 

aToCompare = a[1:] 
bToCompare = b[1:] 

c = filter(lambda x: (not(x in aToCompare)), bToCompare) 
print c 
2

Vous pouvez utiliser des ensembles:

>>> list1=[1,2,3,4] 
>>> list2=[1,5,3,4] 
>>> set(list1[1:]).symmetric_difference(list2[1:]) 
set([2, 5]) 
+0

Je ne pense pas que cela corresponde parfaitement. Ils veulent comparer le premier élément d'une liste au premier élément de l'autre, et le second à la deuxième, etc.Puisque les ensembles ne sont pas commandés, je ne pense pas que ce soit correct pour ce problème. – MatrixFrog

+0

Encore, les ensembles sont une manière intéressante de traiter ce type de problème ... – RyanWilcox

0

En supposant que les deux types sont égaux et ont la même longueur:

list1=[1,2,3,4] 
list2=[1,5,3,4] 
print list1==list2 
Questions connexes