Wie kann ich zwei Listen in Python vergleichen und Übereinstimmungen zurückgeben?


380

Ich möchte zwei Listen nehmen und die Werte finden, die in beiden erscheinen.

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

returnMatches(a, b)

würde [5]zum Beispiel zurückkehren.


4
Die Antworten unten scheinen mir alle falsch zu sein. Was passiert, wenn eine Zahl in einer der beiden Listen wiederholt wird? Sicher möchten Sie wissen, dass (?) (Z. B. sagen beide Listen zweimal '5'). Jede Lösung, die Sätze verwendet, entfernt sofort alle wiederholten Elemente und Sie verlieren diese Info.
MH

Antworten:


486

Nicht der effizienteste, aber bei weitem der naheliegendste Weg, dies zu tun, ist:

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

Wenn die Reihenfolge von Bedeutung ist, können Sie dies mit Listenverständnis wie folgt tun:

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

(funktioniert nur für gleich große Listen, was die Reihenfolge der Bedeutung impliziert).


15
Achtung, das Listenverständnis ist nicht unbedingt die schnellere Option. Bei größeren Sätzen (bei denen die Leistung am wahrscheinlichsten von Bedeutung ist) ist der bitweise Vergleich ( &) oder set(a).intersection(b)genauso schnell oder schneller als das Listenverständnis.
Joshmaker

24
Noch ein Hinweis zur Vorsicht: Das Listenverständnis findet die Werte, die in beiden an den gleichen Positionen erscheinen (dies ist, was SilentGhost mit "Reihenfolge ist signifikant" meinte). Die festgelegten Schnittlösungen finden auch Übereinstimmungen an VERSCHIEDENEN Positionen. Dies sind Antworten auf 2 ganz unterschiedliche Fragen ... (die Frage der
Operation

Wie machen Sie das, wenn Ihre Listen Listen von Listen sind, dh a = [[0,0], [1,0]] und b = [[2,3], [0,0]]
Schneems

3
Was wäre die zeitliche Komplexität des ersten Beispiels set(a) & set(b)?
AdjunctProfessorFalcon

Beachten Sie, dass dies nicht funktioniert, wenn beide Sätze leer sind und Sie erwarten, dass der Vergleich erfolgreich ist. Wechseln Sie also zu "(Satz (a) und Satz (b)) oder (nicht a und nicht b)"
Neil McGill

395

Verwenden Sie set.intersection () , es ist schnell und lesbar.

>>> set(a).intersection(b)
set([5])

28
Diese Antwort weist eine gute algorithmische Leistung auf, da nur eine der Listen (kürzer sollte bevorzugt werden) zur schnellen Suche in eine Gruppe umgewandelt wird und die andere Liste durchlaufen wird, um ihre Elemente in der Gruppe nachzuschlagen.
u0b34a0f6ae

18
bool(set(a).intersection(b))für TrueoderFalse
Akshay

6
Diese Antwort ist flexibler und lesbarer, da die Benutzer möglicherweise differenceoder benötigen union.
Shihe Zhang

Was ist, wenn ich Objekte als Listenelemente habe und nur teilweise Übereinstimmungen möchte, dh nur einige Attribute müssen übereinstimmen, damit sie als übereinstimmendes Objekt betrachtet werden?
CGFoX

Gibt es einen Leistungsunterschied für .intersection()vs &?
Brandonbanks

106

Ein schneller Leistungstest, der die Lösung von Lutz zeigt, ist das Beste:

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)

Dies sind die Ergebnisse auf meinem Computer:

# 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

Natürlich sollte jeder künstliche Leistungstest mit einem Körnchen Salz durchgeführt werden. Da die set().intersection()Antwort jedoch mindestens so schnell wie die anderen Lösungen und auch am besten lesbar ist, sollte sie die Standardlösung für dieses häufig auftretende Problem sein.


Set entfernt tatsächlich Wiederholungen, also funktioniert es in meinem Fall nicht
rgralma

@rgralma, das setaus einem vorhandenen ein neues macht, listentfernt nichts aus dem Original list. Wenn Sie möchten, dass eine spezielle Logik Duplikate in einer Liste behandelt, müssen Sie meiner Meinung nach eine neue Frage stellen, da die Antwort spezifisch sein muss, wie Duplikate behandelt werden sollen.
Joshmaker


15

Der einfachste Weg, dies zu tun, ist die Verwendung von Sets :

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


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'])**

1
Die akzeptierte Antwort funktioniert nicht für Listen, die Zeichenfolgen enthalten. Dieser tut es.
Antony

12

Sie können dies auch versuchen, indem Sie gemeinsame Elemente in einer neuen Liste behalten.

new_list = []
for element in a:
    if element in b:
        new_list.append(element)

5

Möchten Sie Duplikate? Wenn nicht, sollten Sie stattdessen Sets verwenden:


>>> set([1, 2, 3, 4, 5]).intersection(set([9, 8, 7, 6, 5]))
set([5])

Wenn Sie wirklich Listen möchten, überschneiden sich java2s.com/Code/Python/List/Functiontointersecttwolists.htm >>> ([1, 2, 3, 4, 5], [9, 8, 7, 6, 5]) [5 ]
Timothy Pratley

Laut doc - ... sind fehleranfällige Konstruktionen wie Set ('abc') & 'cbs' zugunsten des besser lesbaren Set ('abc'). Intersection ('cbs') ausgeschlossen. - docs.python.org/library/sets.html
Aaron Newton

5

Eine andere, etwas funktionalere Möglichkeit, die Listengleichheit für Liste 1 (lst1) und Liste 2 (lst2) zu überprüfen, wenn Objekte die Tiefe eins haben und die Reihenfolge beibehalten wird, ist:

all(i == j for i, j in zip(lst1, lst2))   

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 

Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Donald Duck

4

Kann auch itertools.product verwenden.

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

3

Sie können verwenden

def returnMatches(a,b):
       return list(set(a) & set(b))

3

Sie können verwenden:

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

Ausgabe:

set([1, 7, 9])

4
Wie unterscheidet sich das von der akzeptierten Antwort von vor mehr als 6 Jahren?
tmdavison

1
Nun, ich schrieb das komplette Detail mit Ausgabe und gut für Anfänger Python
Adnan Ghaffar

2

Wenn Sie einen booleschen Wert wünschen:

>>> 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

1

Die folgende Lösung funktioniert für jede Reihenfolge von Listenelementen und unterstützt auch, dass beide Listen unterschiedlich lang sind.

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]

1
Numpy hat eine spezielle Funktion dafür:np.intersect1d(list1, list2)
Obchardon

0

Die Verwendung der __and__Attributmethode funktioniert ebenfalls.

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

oder einfach

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

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.

4
Die Frage war für Liste und kein Satz. Die Verwendung des &Operators am Set wird bereits von SilentGhost in der akzeptierten Antwort beantwortet
dWinder

0

Ich habe gerade Folgendes verwendet und es hat bei mir funktioniert:

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)

Dies würde dann 5 in Ihrem Fall drucken. Wahrscheinlich keine großartige Leistung.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.