Jak mogę porównać dwie listy w pythonie i zwrócić wyniki


379

Chcę wziąć dwie listy i znaleźć wartości, które pojawiają się w obu.

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

returnMatches(a, b)

wróciłby [5]na przykład.


4
Wszystkie poniższe odpowiedzi wydają mi się błędne. Co się stanie, jeśli liczba zostanie powtórzona na którejkolwiek z list, z pewnością chcesz wiedzieć, że (?) (Np. Powiedzmy, że obie listy mają „5” dwa razy) Każde rozwiązanie wykorzystujące zestawy natychmiast usunie wszystkie powtarzane elementy i stracisz ta informacja.
MH

Odpowiedzi:


486

Nie najskuteczniejszy, ale zdecydowanie najbardziej oczywisty sposób to:

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

jeśli kolejność jest znacząca, możesz to zrobić za pomocą następujących pojęć:

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

(działa tylko w przypadku list o jednakowej wielkości, co sugeruje znaczenie kolejności).


15
Uwaga uwaga, lista jest zrozumienie nie koniecznie szybsza opcja. W przypadku większych zestawów (gdzie wydajność najprawdopodobniej będzie miała znaczenie) porównanie bitowe ( &) lub set(a).intersection(b)będzie tak samo szybkie lub szybsze jak zrozumienie listy.
Joshmaker

24
Kolejna uwaga: na podstawie listy znajduje się wartość, która pojawia się zarówno na SAMYCH pozycjach (to właśnie SilentGhost rozumie przez „porządek jest znaczący”). Rozwiązania dotyczące skrzyżowań znajdą również dopasowania na INNYCH pozycjach. To są odpowiedzi na 2 zupełnie różne pytania ... (pytanie op jest niejednoznaczne, o które pyta)
drevicko

Jak to zrobić, jeśli listy są listami, tj. A = [[0,0], [1,0]] ib = [[2,3], [0,0]]
Schneems,

3
Jaka byłaby złożoność czasowa pierwszego przykładu set(a) & set(b)?
AdjunctProfessorFalcon

Uwaga: to nie działa, jeśli oba zestawy są puste i oczekuje się, że porównanie się powiedzie. Więc zmień na „(zestaw (a) i zestaw (b)) lub (nie a i nie b)”
Neil McGill

395

Użyj set.intersection () , jest szybki i czytelny.

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

28
Ta odpowiedź ma dobrą wydajność algorytmiczną, ponieważ tylko jedna z list (powinna być preferowana krótsza) jest zamieniana w zestaw do szybkiego wyszukiwania, a druga lista jest przeglądana w poszukiwaniu jej elementów w zestawie.
u0b34a0f6ae

18
bool(set(a).intersection(b))for TrueorFalse
Akshay,

6
Ta odpowiedź jest bardziej elastyczna i czytelna, ponieważ ludzie mogą potrzebować differencelub union.
Shihe Zhang,

Co jeśli mam obiekty jako elementy listy i chcę tylko częściowe dopasowania, tj. Tylko niektóre atrybuty muszą się zgadzać, aby można je było uznać za pasujący obiekt?
CGFoX

Czy jest jakaś różnica w wydajności dla .intersection()vs &?
brandonbanks,

106

Szybki test wydajności pokazujący rozwiązanie Lutza jest najlepszy:

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)

Oto wyniki na moim komputerze:

# 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

Oczywiście, każdy test sztucznej wydajności powinien być wykonywany z ziarenkiem soli, ale ponieważ set().intersection()odpowiedź jest co najmniej tak szybka jak inne rozwiązania, a także najbardziej czytelna, powinna być standardowym rozwiązaniem tego powszechnego problemu.


Zestaw faktycznie usuwa powtórzenia, więc w moim przypadku nie zadziała
rgralma

@rgralma dokonanie nowego setz istniejącego listnie usunie niczego z oryginału list. Jeśli chcesz, aby specjalna logika obsługiwała duplikaty na liście, myślę, że musisz zadać nowe pytanie, ponieważ odpowiedź będzie musiała być specyficzna dla tego, jak chcesz obsługiwać duplikaty.
Joshmaker


15

Najprostszym sposobem na to jest użycie zestawów :

>>> 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
Akceptowana odpowiedź nie działa w przypadku list zawierających ciągi znaków. Ten robi.
Antony

12

Możesz także tego spróbować, utrzymując wspólne elementy na nowej liście.

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

5

Czy chcesz duplikaty? Jeśli nie, możesz zamiast tego użyć zestawów:


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

Jeśli naprawdę chcesz listy, java2s.com/Code/Python/List/Functiontointersecttwolists.htm >>> intersect ([1, 2, 3, 4, 5], [9, 8, 7, 6, 5]) [5 ]
Timothy Pratley,

Według doc - ... wyklucza podatne na błędy konstrukcje, takie jak Set („abc”) i „cbs” na korzyść bardziej czytelnego zestawu („abc”). Przecięcie („cbs”). - docs.python.org/library/sets.html
Aaron Newton

5

innym nieco bardziej funkcjonalnym sposobem sprawdzenia równości listy dla listy 1 (Ist1) i listy 2 (IST2), gdzie obiekty mają głębokość 1 i która zachowuje kolejność, jest:

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 

Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi.
Kaczor Donald

4

Może również używać itertools.product.

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

3

Możesz użyć

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

3

Możesz użyć:

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

Wynik:

set([1, 7, 9])

4
czym to się różni od przyjętej odpowiedzi sprzed ponad 6 lat?
tmdavison

1
Cóż, napisałem pełny szczegół z wyjściem i dobrym dla początkującego pytona
Adnan Ghaffar

2

Jeśli chcesz wartość logiczną:

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

Poniższe rozwiązanie działa dla dowolnej kolejności elementów listy, a także obsługuje obie listy o różnej długości.

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 ma do tego specjalną funkcję:np.intersect1d(list1, list2)
obchardon

0

Korzystanie __and__metoda działa również atrybut.

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

lub po prostu

>>> 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
Pytanie dotyczyło listy i nie było zestawu. użycie &operatora na planie jest już odpowiedzią SilentGhost w zaakceptowanej odpowiedzi
dWinder

0

Właśnie użyłem następujących i zadziałało to dla mnie:

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)

spowoduje to wydrukowanie 5 w twoim przypadku. Prawdopodobnie nie pod względem wydajności.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.