Vergleich der gemeinsamen Elemente zwischen zwei Listen

143
def common_elements(list1, list2):
    """
    Return a list containing the elements which are in both list1 and list2

    >>> common_elements([1,2,3,4,5,6], [3,5,7,9])
    [3, 5]
    >>> common_elements(['this','this','n','that'],['this','not','that','that'])
    ['this', 'that']
    """
    for element in list1:
        if element in list2:
            return list(element)

Habe das bisher, kann es aber nicht zum Laufen bringen!

Irgendwelche Ideen?

Daniel
quelle
1
Hallo, können Sie einige Details hinzufügen, wie Sie den Code verwenden möchten? Wenn dies eine Aufgabe abschließen soll, ist es möglicherweise besser, eine Lösung zu wählen, die den "pythonischen" Weg einschließt. Wenn jedoch Effizienz Ihr Anliegen ist, ist der "Pythonic" -Weg wahrscheinlich nicht die effizienteste Lösung. Wenn Sie uns zu diesen Details beraten, können Sie mit Lösungen Ihr Problem lösen.
Matt C

Antworten:

277
>>> list1 = [1,2,3,4,5,6]
>>> list2 = [3, 5, 7, 9]
>>> list(set(list1).intersection(list2))
[3, 5]
SilentGhost
quelle
1
+1 aber persönlich hatte ich frozenset verwendet, da es unveränderlich ist und so als Wörterbuchschlüssel usw. verwendet werden kann
zebrabox
19
Dies gibt die / unique / common-Elemente zurück, jedoch keine wiederholten Elemente, die möglicherweise vorhanden sind.
Dologan
@ SilentGhost. So erhalten Sie die Anzahl der übereinstimmenden Elemente aus zwei Listen. In diesem Fall ist es 2.
Poka
@Poka len (Liste (set (Liste1) .intersection (Liste2))
Dharmanshu Kamra
2
Zu Ihrer Information. Dies ist definitiv schneller als die von Tamás vorgeschlagene Lösung, aber für den Anwendungsfall, den ich mir angesehen habe, als ich auf dieser Seite gelandet bin, war es wichtig, die ursprüngliche Reihenfolge der Elemente für die nachgefilterten Elemente beizubehalten. Diese Methode verliert die Reihenfolge, während die Listenverständnismethode die Reihenfolge beibehält. Wichtig, wenn jemand dies berücksichtigen muss. Vielen Dank.
Agftrading
41

Sie können auch Mengen verwenden und die Gemeinsamkeiten in einer Zeile erhalten: Subtrahieren Sie die Menge, die die Unterschiede enthält, von einer der Mengen.

A = [1,2,3,4]
B = [2,4,7,8]
commonalities = set(A) - (set(A) - set(B))
BeyondRubicon
quelle
4
Dies wandelt A in zweimal um, was unnötig verschwenderisch ist.
wim
35

Die von S.Mark und SilentGhost vorgeschlagenen Lösungen zeigen Ihnen im Allgemeinen, wie es auf pythonische Weise gemacht werden sollte, aber ich dachte, Sie könnten auch davon profitieren, wenn Sie wissen, warum Ihre Lösung nicht funktioniert. Das Problem ist, dass Sie nur dieses einzelne Element zurückgeben, sobald Sie das erste gemeinsame Element in den beiden Listen finden. Ihre Lösung kann behoben werden, indem Sie eine resultListe erstellen und die allgemeinen Elemente in dieser Liste sammeln:

def common_elements(list1, list2):
    result = []
    for element in list1:
        if element in list2:
            result.append(element)
    return result

Eine noch kürzere Version mit Listenverständnis:

def common_elements(list1, list2):
    return [element for element in list1 if element in list2]

Wie gesagt, dies ist jedoch eine sehr ineffiziente Methode. Die in Python integrierten Set-Typen sind weitaus effizienter, da sie intern in C implementiert sind.

Tamás
quelle
1
Großartig für beide Vorschläge
dlewin
1
HINWEIS: Die oben genannten Methoden funktionieren nur für Listen gleicher Größe. Wenn Sie wie ich mit Listen ungleicher Größe arbeiten, müssen Sie die Reihenfolge basierend auf len () auswerten, bevor Sie die Funktion aufrufen: list1 = [2,2,2], list2 [2,3] -> [2,2,2] list1 = [2,3], list2 [2,2,2] -> [2]
redthumb
29

benutze set intersections, set (list1) & set (list2)

>>> def common_elements(list1, list2):
...     return list(set(list1) & set(list2))
...
>>>
>>> common_elements([1,2,3,4,5,6], [3,5,7,9])
[3, 5]
>>>
>>> common_elements(['this','this','n','that'],['this','not','that','that'])
['this', 'that']
>>>
>>>

Beachten Sie, dass die Ergebnisliste eine andere Reihenfolge als die ursprüngliche Liste haben kann.

SIE
quelle
Danke für die Hilfe. Verstehe, wo ich falsch gelaufen bin und woran ich beim nächsten Mal arbeiten soll. :)
Daniel
5
tolle Lösung. Gibt es auch eine Möglichkeit, die Ordnung damit zu erhalten?
Tarrasch
14

Sie können ein einfaches Listenverständnis verwenden:

x=[1,2,3,4]
y=[3,4,5]
common = [i for i in x if i in y]
common: [3,4]
Mahdi Ghelichi
quelle
9

Set ist ein weiterer Weg, wie wir dies lösen können

a = [3,2,4]
b = [2,3,5]
set(a)&set(b)
{2, 3}
Neo
quelle
9

list1 = [1,2,3,4,5,6] list2 = [3,5,7,9]

Ich weiß, dass 3 Wege dies lösen können. Natürlich könnte es mehr geben.

1-

common_elements = [e for e in list1 if e in list2]

2-

import numpy as np
common_elements = np.intersect1d(list1, list2)

3-

common_elements = set(list1).intersection(list2)

Der dritte Weg ist der schnellste, da Sets mithilfe von Hash-Tabellen implementiert werden.

Mahmoud Reda
quelle
8

Die vorherigen Antworten arbeiten alle daran, die eindeutigen gemeinsamen Elemente zu finden, berücksichtigen jedoch nicht die wiederholten Elemente in den Listen. Wenn Sie möchten, dass die allgemeinen Elemente in derselben Nummer angezeigt werden, wie sie in den Listen gemeinsam aufgeführt sind, können Sie den folgenden Einzeiler verwenden:

l2, common = l2[:], [ e for e in l1 if e in l2 and (l2.pop(l2.index(e)) or True)]

Das or TrueTeil ist nur erforderlich, wenn Sie erwarten, dass Elemente ausgewertet werden False.

Dologan
quelle
Tolle Lösung, scheint die gründlichste, wenn auch etwas knappe
Hendeca
Dies sollte die Antwort sein, die ausgewählt werden sollte! Ich gehe davon aus, dass es auch für ungleiche Listen funktioniert. Auch die meisten Lösungen verwenden, setdie nicht stabil sind (auch bekannt als die Bestellung geht verloren).
Lebensbalance
7

Ich verglich jede Methode, die in jeder Antwort erwähnt wurde. In diesem Moment verwende ich Python 3.6.3 für diese Implementierung. Dies ist der Code, den ich verwendet habe:

import time
import random
from decimal import Decimal


def method1():
    common_elements = [x for x in li1_temp if x in li2_temp]
     print(len(common_elements))


def method2():
    common_elements = (x for x in li1_temp if x in li2_temp)
    print(len(list(common_elements)))


def method3():
    common_elements = set(li1_temp) & set(li2_temp)
    print(len(common_elements))


def method4():
    common_elements = set(li1_temp).intersection(li2_temp)
    print(len(common_elements))


if __name__ == "__main__":
    li1 = []
    li2 = []
    for i in range(100000):
        li1.append(random.randint(0, 10000))
        li2.append(random.randint(0, 10000))

    li1_temp = list(set(li1))
    li2_temp = list(set(li2))

    methods = [method1, method2, method3, method4]
    for m in methods:
        start = time.perf_counter()
        m()
        end = time.perf_counter()
        print(Decimal((end - start)))

Wenn Sie diesen Code ausführen, können Sie sehen, dass Sie fast die gleiche Leistung erzielen, wenn Sie Liste oder Generator verwenden (wenn Sie über Generator iterieren und ihn nicht nur verwenden. Ich habe dies getan, als ich den Generator gezwungen habe, die Länge zu drucken). Wenn Sie jedoch set verwenden, erhalten Sie eine viel bessere Leistung. Auch wenn Sie die Schnittmethode verwenden, erhalten Sie eine etwas bessere Leistung. Das Ergebnis jeder Methode in meinem Computer ist unten aufgeführt:

  1. Methode 1: 0,8150673999999999974619413478649221360683441
  2. Methode 2: 0,8329545000000001531148541289439890533685684
  3. Methode 3: 0,0016547000000000089414697868051007390022277
  4. method4: 0.0010262999999999244948867271887138485908508
Sabre Solooki
quelle
5

Dies ist mein Vorschlag, ich denke, es ist einfacher mit Mengen als mit einer for-Schleife

def unique_common_items(list1, list2):
   # Produce the set of *unique* common items in two lists.
   return list(set(list1) & set(list2))
Elasri
quelle
2

Warum nicht verwenden list comprehension?

Halblinienlösung:

common_elements = [x for x in list1 if x in list2]
Seralouk
quelle
0

1) Methode1, die Liste1 speichert, ist ein Wörterbuch und iteriert dann jedes Element in Liste2

def findarrayhash(a,b):
    h1={k:1 for k in a}
    for val in b:
        if val in h1:
            print("common found",val)
            del h1[val]
        else:
            print("different found",val)
    for key in h1.iterkeys():
        print ("different found",key)

Gemeinsame und unterschiedliche Elemente finden:

2) Methode2 mit set

def findarrayset(a,b):
    common = set(a)&set(b)
    diff=set(a)^set(b)
    print list(common)
    print list(diff) 
JS
quelle
-1

Verwenden Sie einen Generator:

common = (x for x in list1 if x in list2)

Der Vorteil hierbei ist, dass dies auch bei Verwendung großer Listen oder anderer großer Iterables in konstanter Zeit (fast augenblicklich) wiedergegeben wird.

Beispielsweise,

list1 =  list(range(0,10000000))
list2=list(range(1000,20000000))
common = (x for x in list1 if x in list2)

Alle anderen Antworten hier werden mit diesen Werten für Liste1 und Liste2 sehr lange dauern.

Sie können die Antwort dann mit wiederholen

for i in common: print(i)

Oder konvertieren Sie es in eine Liste mit

list(i)
Cowlinator
quelle
Dies liefert keine Antwort. Das Ergebnis ist eher ein Generator als die Liste der gemeinsamen Elemente.
Josiekre
1
Richtig, es wird ein Generator erstellt, der eine Antwort ist. Die Frage war, irgendwie die gemeinsamen Elemente der 2 Listen zu bekommen, was dieser Generator tut. Iterieren Sie den Generator einfach wie folgt : for i in common: print(i). Generatoren sind Iterables, die häufig anstelle anderer Iterables wie Listen verwendet werden.
Cowlinator