Bagaimana saya bisa membandingkan dua daftar dalam python dan mengembalikan kecocokan

381

Saya ingin mengambil dua daftar dan menemukan nilai yang muncul di keduanya.

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

returnMatches(a, b)

akan kembali [5], misalnya.

tehryan
sumber
4
Jawaban di bawah ini sepertinya salah bagi saya. Apa yang terjadi jika suatu nomor diulang dalam kedua daftar, tentunya Anda ingin tahu bahwa (?) (Mis., Katakanlah kedua daftar memiliki '5' dua kali) Setiap solusi menggunakan set akan segera menghapus semua item yang diulang dan Anda akan kehilangan info itu.
MH
Kemungkinan rangkap dari Bagaimana menemukan persimpangan daftar?
Kushan Gunasekera

Jawaban:

487

Bukan yang paling efisien, tetapi sejauh ini cara yang paling jelas untuk melakukannya adalah:

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

jika pesanan signifikan, Anda dapat melakukannya dengan daftar pemahaman seperti ini:

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

(hanya berfungsi untuk daftar berukuran sama, yang menyiratkan signifikansi pesanan).

SilentGhost
sumber
15
Sebagai catatan kehati-hatian, pemahaman daftar tidak selalu merupakan pilihan yang lebih cepat. Untuk set yang lebih besar (di mana kinerja kemungkinan besar menjadi masalah) perbandingan bitwise ( &) atau set(a).intersection(b)akan secepat atau lebih cepat dari daftar pemahaman.
Joshmaker
24
Catatan lain untuk berhati-hati: pemahaman daftar menemukan nilai-nilai yang muncul di kedua posisi yang SAMA (inilah yang dimaksud oleh SilentGhost dengan "urutan signifikan"). Solusi persimpangan yang ditetapkan juga akan menemukan kecocokan pada posisi BERBEDA. Ini adalah jawaban untuk 2 pertanyaan yang sangat berbeda ... (pertanyaan op bersifat mendua yang ditanyakan)
drevicko
Bagaimana Anda melakukan ini jika daftar Anda adalah daftar daftar yaitu a = [[0,0], [1,0]] dan b = [[2,3], [0,0]]
Schneems
3
Apa yang akan menjadi kompleksitas waktu dari contoh pertama set(a) & set(b)?
AdjunctProfessorFalcon
Catatan, ini tidak berfungsi jika kedua set kosong dan Anda mengharapkan perbandingan untuk lulus. Jadi ubah ke "(atur (a) dan atur (b)) atau (bukan a dan bukan b)"
Neil McGill
395

Gunakan set.intersection () , cepat dan mudah dibaca.

>>> set(a).intersection(b)
set([5])
Dennis
sumber
28
Jawaban ini memiliki kinerja algoritmik yang baik, karena hanya satu dari daftar (lebih pendek yang lebih disukai) yang diubah menjadi satu set untuk pencarian cepat, dan daftar lainnya dilacak mencari item-itemnya di set.
u0b34a0f6ae
18
bool(set(a).intersection(b))untuk TrueatauFalse
Akshay
6
Jawaban ini lebih fleksibel dan mudah dibaca, karena orang mungkin perlu differenceatau union.
Shihe Zhang
Bagaimana jika saya memiliki objek sebagai elemen daftar dan hanya ingin kecocokan parsial, yaitu, hanya beberapa atribut yang harus cocok agar dianggap sebagai objek yang cocok?
CGFoX
Apakah ada perbedaan kinerja untuk .intersection()vs &?
brandonbanks
106

Tes kinerja cepat yang menunjukkan solusi Lutz adalah yang terbaik:

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)

Ini adalah hasil di mesin saya:

# 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

Jelas, setiap tes kinerja buatan harus diambil dengan sebutir garam, tetapi karena set().intersection()jawabannya setidaknya secepat solusi lain, dan juga yang paling mudah dibaca, itu harus menjadi solusi standar untuk masalah umum ini.

Joshmaker
sumber
Set sebenarnya menghapus pengulangan, jadi dalam kasus saya tidak akan bekerja
rgralma
@rgralma membuat yang baru setdari yang sudah ada listtidak akan menghapus apa pun dari aslinya list. Jika Anda ingin logika khusus untuk menangani duplikat dalam daftar, saya pikir Anda perlu mengajukan pertanyaan baru karena jawabannya harus spesifik untuk bagaimana Anda ingin duplikat ditangani.
Joshmaker
67

Saya lebih suka jawaban berdasarkan set, tapi tetap saja ada yang berhasil

[x for x in a if x in b]
SingleNegationElimination
sumber
15

Cara termudah untuk melakukannya adalah dengan menggunakan set :

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

Cara cepat:

list(set(a).intersection(set(b)))
DisusterAussie
sumber
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
sumber
1
Jawaban yang diterima tidak berfungsi untuk daftar yang berisi string. Yang ini.
Antony
12

Anda juga dapat mencoba ini, dengan menyimpan elemen umum dalam daftar baru.

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

Apakah Anda ingin duplikat? Jika tidak, Anda sebaiknya menggunakan set sebagai gantinya:


>>> set([1, 2, 3, 4, 5]).intersection(set([9, 8, 7, 6, 5]))
set([5])
Timothy Pratley
sumber
Jika Anda benar-benar menginginkan daftar, java2s.com/Code/Python/List/Functiontointersecttwolists.htm >>> intersect ([1, 2, 3, 4, 5], [9, 8, 7, 6, 5]) [5 ]
Timothy Pratley
Menurut dokumen - ... menghalangi konstruksi rawan kesalahan seperti Set ('abc') & 'cbs' yang mendukung Set yang lebih mudah dibaca ('abc'). Intersection ('cbs'). - docs.python.org/library/sets.html
Aaron Newton
5

cara lain yang sedikit lebih fungsional untuk memeriksa daftar persamaan untuk daftar 1 (lst1) dan daftar 2 (lst2) di mana objek memiliki kedalaman satu dan yang menjaga urutannya adalah:

all(i == j for i, j in zip(lst1, lst2))   
itmatters
sumber
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
sumber
1
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang bagaimana dan / atau mengapa memecahkan masalah akan meningkatkan nilai jangka panjang jawaban.
Donald Duck
4

Dapat menggunakan itertools.product juga.

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

Kamu bisa menggunakan

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

Kamu bisa menggunakan:

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

Keluaran:

set([1, 7, 9])
Adnan Ghaffar
sumber
4
apa bedanya dengan jawaban yang diterima dari 6+ tahun yang lalu?
tmdavison
1
Yah, saya menulis detail lengkap dengan output dan bagus untuk pemula python
Adnan Ghaffar
2

Jika Anda menginginkan nilai boolean:

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

Solusi berikut berfungsi untuk setiap urutan item daftar dan juga mendukung kedua daftar dengan panjang yang berbeda.

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
sumber
1
Numpy memiliki fungsi spesifik untuk itu:np.intersect1d(list1, list2)
obchardon
0

Menggunakan __and__metode atribut juga berfungsi.

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

atau sederhana

>>> set([1, 2, 3, 4, 5]).__and__(set([9, 8, 7, 6, 5]))
set([5])
>>>    
SuperNova
sumber
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
sumber
4
Pertanyaannya adalah untuk daftar dan tidak ada set. penggunaan &operator di set sudah dijawab oleh SilentGhost dalam jawaban yang diterima
dWinder
0

Saya hanya menggunakan yang berikut ini dan itu berhasil untuk saya:

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)

ini kemudian akan mencetak 5 dalam kasus Anda. Mungkin kinerja yang tidak bijaksana.

LRBrady
sumber