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.


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

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


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

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.


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


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


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

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

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

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 

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

3

Kamu bisa menggunakan

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

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

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

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]

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

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.