Comment puis-je comparer deux listes en python et retourner des correspondances

381

Je veux prendre deux listes et trouver les valeurs qui apparaissent dans les deux.

a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]

returnMatches(a, b)

reviendrait [5], par exemple.

tehryan
la source
4
Les réponses ci-dessous me semblent toutes fausses. Que se passe-t-il si un nombre est répété dans l'une ou l'autre liste, vous voudrez sûrement savoir que (?) (Par exemple, disons que les deux listes ont '5' deux fois) Toute solution utilisant des ensembles supprimera immédiatement tous les éléments répétés et vous perdrez cette info.
MH
Copie possible de Comment trouver l'intersection de liste?
Kushan Gunasekera

Réponses:

487

Ce n'est pas le plus efficace, mais de loin le moyen le plus évident de le faire est:

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a) & set(b)
{5}

si l'ordre est important, vous pouvez le faire avec des listes de compréhension comme celle-ci:

>>> [i for i, j in zip(a, b) if i == j]
[5]

(ne fonctionne que pour les listes de taille égale, ce qui implique une signification d'ordre).

SilentGhost
la source
15
Attention, la compréhension de la liste n'est pas forcément l'option la plus rapide. Pour les ensembles plus grands (où les performances sont les plus susceptibles d'avoir de l'importance), la comparaison au niveau du bit ( &) ou set(a).intersection(b)sera aussi rapide ou plus rapide que la compréhension de la liste.
Joshmaker
24
Une autre note de prudence: la compréhension de la liste trouve les valeurs qui apparaissent dans les deux aux mêmes positions (c'est ce que SilentGhost entendait par «l'ordre est significatif»). Les solutions d'intersection définies trouveront également des correspondances à DIFFÉRENTES positions. Ce sont des réponses à 2 questions très différentes ... (la question de l'op est ambigu quant à ce qu'il pose)
drevicko
Comment faites-vous cela si vos listes sont des listes de listes, c'est-à-dire a = [[0,0], [1,0]] et b = [[2,3], [0,0]]
Schneems
3
Quelle serait la complexité temporelle du premier exemple set(a) & set(b)?
AdjunctProfessorFalcon
Remarque, cela ne fonctionne pas si les deux ensembles sont vides et que vous vous attendez à ce que la comparaison réussisse. Alors changez en "(set (a) et set (b)) ou (not a and not b)"
Neil McGill
395

Utilisez set.intersection () , c'est rapide et lisible.

>>> set(a).intersection(b)
set([5])
Dennis
la source
28
Cette réponse a de bonnes performances algorithmiques, car une seule des listes (la plus courte devrait être préférée) est transformée en un ensemble pour une recherche rapide, et l'autre liste est parcourue en recherchant ses éléments dans l'ensemble.
u0b34a0f6ae
18
bool(set(a).intersection(b))pour TrueouFalse
Akshay
6
Cette réponse est plus flexible et plus lisible, car les gens peuvent avoir besoin de differenceou union.
Shihe Zhang
Que se passe-t-il si j'ai des objets en tant qu'éléments de liste et ne souhaite que des correspondances partielles, c'est-à-dire que seuls certains attributs doivent correspondre pour qu'il soit considéré comme un objet correspondant?
CGFoX
Existe-t-il une différence de performances pour .intersection()vs &?
brandonbanks
106

Un test de performance rapide montrant la solution de Lutz est le meilleur:

import time

def speed_test(func):
    def wrapper(*args, **kwargs):
        t1 = time.time()
        for x in xrange(5000):
            results = func(*args, **kwargs)
        t2 = time.time()
        print '%s took %0.3f ms' % (func.func_name, (t2-t1)*1000.0)
        return results
    return wrapper

@speed_test
def compare_bitwise(x, y):
    set_x = frozenset(x)
    set_y = frozenset(y)
    return set_x & set_y

@speed_test
def compare_listcomp(x, y):
    return [i for i, j in zip(x, y) if i == j]

@speed_test
def compare_intersect(x, y):
    return frozenset(x).intersection(y)

# Comparing short lists
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]
compare_bitwise(a, b)
compare_listcomp(a, b)
compare_intersect(a, b)

# Comparing longer lists
import random
a = random.sample(xrange(100000), 10000)
b = random.sample(xrange(100000), 10000)
compare_bitwise(a, b)
compare_listcomp(a, b)
compare_intersect(a, b)

Voici les résultats sur ma machine:

# Short list:
compare_bitwise took 10.145 ms
compare_listcomp took 11.157 ms
compare_intersect took 7.461 ms

# Long list:
compare_bitwise took 11203.709 ms
compare_listcomp took 17361.736 ms
compare_intersect took 6833.768 ms

Évidemment, tout test de performance artificiel doit être effectué avec un grain de sel, mais comme la set().intersection()réponse est au moins aussi rapide que les autres solutions, et aussi la plus lisible, elle devrait être la solution standard pour ce problème commun.

Joshmaker
la source
Set supprime les répétitions, donc dans mon cas, ne fonctionnera pas
rgralma
@rgralma créer un nouveau à setpartir d'un existant listne supprimera rien de l'original list. Si vous voulez une logique spéciale pour gérer les doublons dans une liste, je pense que vous devrez poser une nouvelle question car la réponse devra être spécifique à la façon dont vous voulez que les doublons soient traités.
Joshmaker
67

Je préfère les réponses basées sur un ensemble, mais en voici une qui fonctionne quand même

[x for x in a if x in b]
SingleNegationElimination
la source
15

La façon la plus simple de le faire est d'utiliser des ensembles :

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a) & set(b)
set([5])
Greg Hewgill
la source
15

Façon rapide:

list(set(a).intersection(set(b)))
Déplacé Australien
la source
14
>>> s = ['a','b','c']   
>>> f = ['a','b','d','c']  
>>> ss= set(s)  
>>> fs =set(f)  
>>> print ss.intersection(fs)   
   **set(['a', 'c', 'b'])**  
>>> print ss.union(fs)        
   **set(['a', 'c', 'b', 'd'])**  
>>> print ss.union(fs)  - ss.intersection(fs)   
   **set(['d'])**
setz
la source
1
La réponse acceptée ne fonctionne pas pour les listes contenant des chaînes. Celui-ci le fait.
Antony
12

Vous pouvez également essayer ceci, en gardant les éléments communs dans une nouvelle liste.

new_list = []
for element in a:
    if element in b:
        new_list.append(element)
mushfiq
la source
5

Voulez-vous des doublons? Sinon, vous devriez plutôt utiliser des ensembles:


>>> set([1, 2, 3, 4, 5]).intersection(set([9, 8, 7, 6, 5]))
set([5])
Timothy Pratley
la source
Si vous voulez vraiment des listes, java2s.com/Code/Python/List/Functiontointersecttwolists.htm >>> intersect ([1, 2, 3, 4, 5], [9, 8, 7, 6, 5]) [5 ]
Timothy Pratley
Selon le doc - ... exclut les constructions sujettes aux erreurs comme Set ('abc') & 'cbs' en faveur de Set plus lisible ('abc'). Intersection ('cbs'). - docs.python.org/library/sets.html
Aaron Newton
5

une autre façon un peu plus fonctionnelle de vérifier l'égalité des listes pour la liste 1 (lst1) et la liste 2 (lst2) où les objets ont une profondeur un et qui maintient l'ordre est:

all(i == j for i, j in zip(lst1, lst2))   
Cela compte
la source
4
a = [1, 2, 3, 4, 5]
b = [9, 8, 7, 6, 5]

lista =set(a)
listb =set(b)   
print listb.intersection(lista)   
returnMatches = set(['5']) #output 

print " ".join(str(return) for return in returnMatches ) # remove the set()   

 5        #final output 
Harish Verma
la source
1
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la manière et / ou la raison pour laquelle il résout le problème améliorerait la valeur à long terme de la réponse.
Donald Duck
4

Peut également utiliser itertools.product.

>>> common_elements=[]
>>> for i in list(itertools.product(a,b)):
...     if i[0] == i[1]:
...         common_elements.append(i[0])
SuperNova
la source
3

Vous pouvez utiliser

def returnMatches(a,b):
       return list(set(a) & set(b))
Prabhu
la source
3

Vous pouvez utiliser:

a = [1, 3, 4, 5, 9, 6, 7, 8]
b = [1, 7, 0, 9]
same_values = set(a) & set(b)
print same_values

Production:

set([1, 7, 9])
Adnan Ghaffar
la source
4
en quoi est-ce différent de la réponse acceptée d'il y a 6 ans et plus?
tmdavison
1
Eh bien, j'ai écrit le détail complet avec une sortie et bon pour le python débutant
Adnan Ghaffar
2

Si vous voulez une valeur booléenne:

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(b) == set(a)  & set(b) and set(a) == set(a) & set(b)
False
>>> a = [3,1,2]
>>> b = [1,2,3]
>>> set(b) == set(a)  & set(b) and set(a) == set(a) & set(b)
True
Matheus Araujo
la source
1

La solution suivante fonctionne pour n'importe quel ordre des éléments de liste et prend également en charge les deux listes pour être de longueur différente.

import numpy as np
def getMatches(a, b):
    matches = []
    unique_a = np.unique(a)
    unique_b = np.unique(b)
    for a in unique_a:
        for b in unique_b:
            if a == b:
                matches.append(a)
    return matches
print(getMatches([1, 2, 3, 4, 5], [9, 8, 7, 6, 5, 9])) # displays [5]
print(getMatches([1, 2, 3], [3, 4, 5, 1])) # displays [1, 3]
Hafizur Rahman
la source
1
Numpy a une fonction spécifique pour cela:np.intersect1d(list1, list2)
obchardon
0

L'utilisation de la __and__méthode d'attribut fonctionne également.

>>> a = [1, 2, 3, 4, 5]
>>> b = [9, 8, 7, 6, 5]
>>> set(a).__and__(set(b))
set([5])

ou simplement

>>> set([1, 2, 3, 4, 5]).__and__(set([9, 8, 7, 6, 5]))
set([5])
>>>    
SuperNova
la source
0
you can | for set union and & for set intersection.
for example:

    set1={1,2,3}
    set2={3,4,5}
    print(set1&set2)
    output=3

    set1={1,2,3}
    set2={3,4,5}
    print(set1|set2)
    output=1,2,3,4,5

curly braces in the answer.
ravi tanwar
la source
4
La question était pour la liste et aucun ensemble. l'utilisation de l' &opérateur sur le plateau est déjà répondu par SilentGhost dans la réponse acceptée
dWinder
0

Je viens d'utiliser les éléments suivants et cela a fonctionné pour moi:

group1 = [1, 2, 3, 4, 5]
group2 = [9, 8, 7, 6, 5]

for k in group1:
    for v in group2:
        if k == v:
            print(k)

cela afficherait alors 5 dans votre cas. Probablement pas de bonnes performances.

LRBrady
la source